Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
@dabh/eslint-config-populist
Advanced tools
A (one day) auto-updating style at the mercy of the people, and only the people.
A (one day) auto-updating style at the mercy of the people, and only the people.
Today it is still a bespoke set of rules. One has to have goals, no? The copy
below is unfortunately a bit out of date compared to the latest eslint
rules
in index.js
. They remain because reusing the English copy is very likely
even with new and/or slightly different rules.
If you have comments on this or disagree about rules then please reach out to me directly. I want to hear it!
Basics
Identifiers and Primitives
Statements and Techniques
()
around statements like typeof
or delete
.;
must be added at the end of every statement, except when the next character is a closing bracket }
. In that case, they may be omitted.//
// GOOD
//
var f = function add(a, b) {
if (a == b) { return a * 2 } // No `;` here.
return a + b;
};
//
// BAD
//
var f = function add (a, b) {
return a + b
}
//
// GOOD
//
if (x) { return true }
//
// BAD
//
if (x)
while (1)
i ++;
else
//...
//
// BAD
//
if (x) return true;
//
// BAD
//
if (x)
return true;
Vertical screen space is precious, and ease of scanning code is more previous.
//
// GOOD
//
if (x) {
return true;
}
else {
return false;
}
//
// BAD
//
if (x)
{
return true;
}
//
// BAD
//
if (x) {
return true; }
//
// BAD
//
if (x) {
return true;
} else {
return false
}
This makes it easy to see the end of a function or statement
//
// GOOD
//
return callback && callback({ foo: bar });
//
// GOOD
//
return callback && callback({
foo: bar
});
//
// BAD
//
return callback && callback({
foo: bar });
//
// BAD
//
return callback && callback({ foo: bar
});
//
// BAD
//
function q() {
// ...stuff...
}
//
// GOOD
//
function query() {
// ..stuff..
}
//
// BAD
//
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
//
// GOOD
//
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
// BAD
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'nope'
});
// GOOD
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'yup'
});
_
when naming private properties// BAD
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// GOOD
this._firstName = 'Panda';
this
(which is a prototypal object) must use self
.function User (options) {
this.setup();
}
//
// GOOD
//
User.prototype.setup = function () {
var self = this;
setTimeout(function () {
self.ready = true
}, 1000);
};
//
// BAD
//
User.prototype.setup = function () {
var that = this;
setTimeout(function () {
that.ready = true
}, 1000);
};
this
(which is an arbitrary scope) should use that
.//
// BAD
//
function () {
var self = this;
return function() {
console.log(self);
};
}
//
// BAD
//
function () {
var _this = this;
return function() {
console.log(_this);
};
}
//
// GOOD
//
function () {
var that = this;
return function() {
console.log(that);
};
}
//
// OK
//
var log = function(msg) {
console.log(msg);
};
//
// GOOD
//
var log = function log(msg) {
console.log(msg);
};
Variable declarations are moved up to the top of the function scope anyway, so that's where they belong.
//
// GOOD
//
function (a, b) {
var k;
if (a == b) {
k = true;
}
//...
}
for (var i = 0; i < l; i ++) {
//...
}
//
// BAD
//
function (a, b) {
if (a == b) {
var k = true;
}
//...
}
This makes it easy to scan what is declared in a single block.
//
// GOOD
//
var bazz,
foo,
bar;
//
// BAD
//
var bazz,
foo,
bar;
This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.
//
// BAD
//
var i, len, dragonball,
items = getItems(),
goSportsTeam = true;
//
// BAD
//
var i, items = getItems(),
dragonball,
goSportsTeam = true,
len;
//
// GOOD
//
var items = getItems(),
goSportsTeam = true,
dragonball,
length,
i;
This also makes it easier to scan what is declared in a single block (trust me).
//
// GOOD
//
var reallyLongVar,
shorterVar,
fooBar,
foo;
//
// BAD
//
var fooBar,
shorterVar,
foo,
reallyLongVar;
This also makes it easier to scan what is declared in a single block (trust me).
//
// GOOD
//
var reallyLongVar = 10e3,
shorterVar = 5e2,
fooBar = 'foobar',
foo;
//
// OK
//
var reallyLongVar = 10e3,
shorterVar = 5e2,
fooBar = 'foobar',
foo;
//
// BAD
//
var foo,
reallyLongVar = 10e3,
shorterVar = 5e2,
fooBar = 'foobar';
It's what god would have wanted.
//
// GOOD
//
var obj = { list: [], expired: false },
bazz = 100,
foo,
bar;
//
// GOOD
//
var bazz = 100,
foo,
bar,
obj;
obj = {
list: [],
expired: false
};
//
// BAD
//
var obj = {
list: [],
expired: false
},
bazz = 100,
foo,
bar;
//
// BAD
//
var bazz = 100,
foo,
bar,
obj = {
list: [],
expired: false
};
//
// GOOD
//
var memo = list.filter(function (i) { return i < 10 }),
bazz = 100,
foo,
bar;
//
// GOOD
//
var bazz = 100,
memo,
foo,
bar;
memo = list.filter(function (i) {
return i < 10;
}).filter(Boolean);
//
// BAD
//
var memo = list.filter(function (i) {
return i < 10
}),
bazz = 100,
foo,
bar;
//
// BAD
//
var bazz = 100,
foo,
bar,
memo = list.filter(function (i) {
return i < 10;
}).filter(Boolean);
//
// BAD
//
var bazz = 100,
foo,
bar,
memo = list.filter(function (i) { return i < 10 })
.filter(Boolean);
{
and a leading space before }
.//
// BAD
//
var foo = {bar: 1};
//
// BAD
//
return {bar: 1};
//
// GOOD
//
var foo = { bar: 1 };
//
// GOOD
//
return { bar: 1 };
:
//
// BAD
//
var foo = { bar:1 };
//
// BAD
//
var foo = {
bar : 1,
bazz : 1
};
//
// GOOD
//
var foo = { bar: 1 };
//
// GOOD
//
var foo = {
bar: 1,
bazz: 1
};
//
// GOOD
//
var foo = {
bar: 1,
bazz: 1
};
Reduces the number of variables managed and object creation is cheap.
//
// GOOD
//
return {
foos: list.filter(function (i) {
return i.type === 'foo';
}),
bars: list.filter(function (i) {
return i.type === 'bar';
})
}
//
// BAD
//
var item = new Object();
//
// GOOD
//
var item = {};
//
// OK
//
var superman = {
class: 'superhero',
default: { clark: 'kent' },
private: true
};
//
// BAD
//
var items = new Array();
// GOOD
var items = [];
var someStack = [];
//
// BAD
//
someStack[someStack.length] = 'abracadabra';
//
// GOOD
//
someStack.push('abracadabra');
var len = items.length,
itemsCopy = [],
i;
//
// BAD
//
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
//
// GOOD
//
itemsCopy = items.slice();
''
for strings//
// BAD
//
var name = "Bob Parr";
//
// GOOD
//
var name = 'Bob Parr';
//
// BAD
//
var fullName = "Bob " + this.lastName;
//
// GOOD
//
var fullName = 'Bob ' + this.lastName;
If overused, long strings with concatenation could impact performance. jsPerf & Discussion
//
// BAD
//
var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
//
// BAD
//
var errorMessage = 'This is a super long error that \
was thrown because of Batman. \
When you stop to think about \
how Batman had anything to do \
with this, you would get nowhere \
fast.';
//
// GOOD
//
var errorMessage = 'This is a super long error that ' +
'was thrown because of Batman.' +
'When you stop to think about ' +
'how Batman had anything to do ' +
'with this, you would get nowhere ' +
'fast.';
//
// GOOD
//
var errorMessage = [
'This is a super long error that ',
'was thrown because of Batman.',
'When you stop to think about',
'how Batman had anything to do',
'with this, you would get nowhere'
'fast.'
].join(' ');
var items,
messages,
length,
i;
messages = [{
state: 'success',
message: 'This one worked.'
}, {
state: 'success',
message: 'This one worked as well.'
}, {
state: 'error',
message: 'This one did not work.'
}];
length = messages.length;
//
// BAD
//
function inbox(messages) {
items = '<ul>';
for (i = 0; i < length; i++) {
items += '<li>' + messages[i].message + '</li>';
}
return items + '</ul>';
}
//
// GOOD
//
function inbox(messages) {
items = [];
for (i = 0; i < length; i++) {
items[i] = messages[i].message;
}
return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
}
Having appropriate space in your code comments makes writing complex code easier to read. It's the "almost literate coding" approach.
docco
-style comments we have historically used we will replace it all together./*
* a-js-file.js: This is some file
*
* (C) 2013 Whomever
* MIT LICENSE
*
*/
//
// ### function myFunction (a, b, c)
// #### @a {string} A variable
// #### @b {boolean} Another variable
// #### @c {object|Array} An object or an array
//
// This is the description to my function.
//
//
// Adding additional padding in your code comments
//
var a = 0;
//
// Along with additional whitespace
//
if (!a) {
console.log('Makes your code easier to read.');
console.log('What are you running out of bytes?');
}
// One line comments
var a = 0;
// and no whitespace
if (!a) {
console.log('make your code harder to read');
console.log('seriously.');
}
/*
* I'm using block comments anywhere but the file header.
*/
// FIXME:
to annotate problems.// TODO:
to annotate solutions to problems.// REMARK:
to annotate possible annotations or open implementation questions (which are not obvious problems).function Calculator() {
// FIXME (index zero): shouldn't use a global here
total = 0;
return this;
}
function Calculator() {
// TODO (indexzero): total should be configurable by an options param
this.total = 0;
return this;
}
function Calculator() {
// shouldn't use a global here
total = 0;
return this;
}
function Calculator() {
// TODO: total should be configurable by an options param
this.total = 0;
return this;
}
Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base!
function Jedi() {
console.log('new jedi');
}
//
// BAD
//
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
//
// GOOD
//
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
this
to help with method chaining.//
// OK
//
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
//
// GOOD
//
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
function Jedi(options) {
options || (options = {});
this.name = options.name || 'no name';
}
Jedi.prototype.getName = function getName() {
return this.name;
};
Jedi.prototype.toString = function toString() {
return 'Jedi - ' + this.getName();
};
if
, while
and for
must have a space between the keyword and the left parenthesis.They aren't functions, and thus better distinguished like this.
//
// GOOD
//
if (a) {
return true;
}
//
// BAD
//
if(a) {
return true;
}
if else
blocks.Eager returns simplifies most control-flow, especially more complex and high-level control-flow.
//
// BAD
//
if (foo) {
callback(null, 'foo');
}
else {
callback(null, 'bar');
}
//
// GOOD
//
if (foo) {
return callback(null, 'foo');
}
callback(null, 'bar');
function
keyword and the left parenthesis.To emphasise the lack of identifier and differentiate them with named functions.
//
// GOOD
//
function (a, b) {}
//
// BAD
//
function(a, b) {}
//
// GOOD
//
function add(a, b) {}
//
// BAD
//
function add (a, b) {}
(
.//
// GOOD
//
if (something === 'foo' && (somethingElse === 'bar'
&& ohYeahThisToo === 'bazz')) {
return false;
}
//
// BAD
//
if (something === 'foo' && (somethingElse === 'bar' &&
ohYeahThisToo === 'bazz')) {
return false;
}
//
// BAD
//
if (something === 'foo' && (somethingElse === 'bar' &&
ohYeahThisToo === 'bazz') {
return false;
}
//
// OK
//
if (list.filter(function (i) { return i.ok }).length > 5) {
return false;
}
// => this.reviewScore = 9;
//
// BAD
//
var totalScore = this.reviewScore + '';
//
// GOOD
//
var totalScore = '' + this.reviewScore;
//
// BAD
//
var totalScore = '' + this.reviewScore + ' total score';
//
// GOOD
//
var totalScore = this.reviewScore + ' total score';
parseInt
for Numbers and always with a radix for type casting.If for whatever reason you are doing something wild and
parseInt
is your bottleneck and need to use Bitshift for performance reasons, leave a comment explaining why and what you're doing.
Numbers
var inputValue = '4';
//
// OK
//
var val = +inputValue;
//
// BAD
//
var val = new Number(inputValue);
//
// BAD
//
var val = inputValue >> 0;
//
// BAD
//
var val = parseInt(inputValue);
//
// GOOD
//
var val = Number(inputValue);
//
// GOOD
//
var val = parseInt(inputValue, 10);
//
// GOOD
//
//
// parseInt was the reason my code was slow.
// Bitshifting the String to coerce it to a
// Number made it a lot faster.
//
var val = inputValue >> 0;
Booleans
var age = 0;
//
// BAD
//
var hasAge = new Boolean(age);
//
// GOOD
//
var hasAge = Boolean(age);
//
// GOOD
//
var hasAge = !!age;
More than one and it's spaghetti.
//
// GOOD
//
var i = 2,
x = i > 5 ? i : 0;
//
// BAD
//
var i = 2,
j = 3,
x = i > 5 ? j > 4 ? j : i : 0;
//
// GOOD
//
return foo
? foo + 1
: bar;
//
// GOOD
//
return foo ? foo + 1 : bar;
//
// GOOD
//
return foo
? function () { return foo + 1 }
: bar;
//
// GOOD
//
return err
? callback(err)
: callback();
//
// BAD
//
return foo ?
foo + 1 :
bar;
//
// BAD
//
return foo
? foo + 1 :
bar;
//
// BAD
//
return foo
? function (wtf) {
return foo + 1; // No multi-line return values!
}
: bar;
return
should be preferred over if (err) { return }
blocks. //
// OK
//
if (err) {
return callback(err);
}
callback();
//
// GOOD
//
return err
? callback(err)
: callback();
If you want more descriptive Errors, use errs.
//
// GOOD
//
throw new Error('I have a call-stack and other good things.');
//
// GOOD
//
callback(new Error('I have a call-stack and other good things.'));
//
// BAD
//
throw 'I have no call-stack no interesting properties.';
//
// BAD
//
callback('I have no call-stack no interesting properties.');
//
// BAD
//
throw { message: 'I have no call-stack no interesting properties.' };
//
// BAD
//
callback({
message: 'I have no call-stack no interesting properties.'
});
Makes it easier to understand what the exports are immediately in the same context.
//
// GOOD
//
var Foo = exports.Foo = function () {
//...
};
//
// BAD
//
var Foo = function () {
//...
};
//
// Lots of other code changing my mental context
// by the time I see Foo again I forgot what it was.
//
exports.Foo = Foo;
Just use async. If you love promises then sorry; this decision is final and not up for debate … ever.
//
// GOOD
//
var async = require('async');
//
// BAD
//
var Q = require('q');
Rule of three. What? It works in fairy tales.
INSERT CODE EXAMPLES HERE
The following files include software modified from
eslint-config-godaddy
with attribution under MIT
© GoDaddy Operating Company 2016index.js bin/eslint-autofix.js
Modifications © Charlie Robbins 2017
FAQs
A (one day) auto-updating style at the mercy of the people, and only the people.
The npm package @dabh/eslint-config-populist receives a total of 1,039 weekly downloads. As such, @dabh/eslint-config-populist popularity was classified as popular.
We found that @dabh/eslint-config-populist demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.