Objects
3.1 Use literal syntax for object creation
Use the literal syntax for object creation.
eslint: no-new-object
const item = new Object();
3.2 Use computed property names
Use computed property names when creating objects with dynamic property names.
Computed property names allow you to define all the properties of an object in one place, rather than adding dynamic keys after the fact.
function getKey(k) {
return `a key named ${k}`;
}
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
function getKey(k) {
return `a key named ${k}`;
}
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
3.3 Use object method shorthand
Use object method shorthand.
eslint: object-shorthand
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
3.4 Use property value shorthand
Use property value shorthand.
eslint: object-shorthand
Shorthand is shorter and more descriptive — the property name itself documents where the value comes from.
const lukeSkywalker = 'Luke Skywalker';
const obj = {
lukeSkywalker,
};
const lukeSkywalker = 'Luke Skywalker';
const obj = {
lukeSkywalker: lukeSkywalker,
};
3.5 Group shorthand properties at the top
Group your shorthand properties at the beginning of your object declaration.
Grouping shorthand properties makes it easy to see at a glance which properties are using the shorthand.
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
3.6 Only quote invalid identifier properties
Only quote properties that are invalid identifiers.
eslint: quote-props
Unquoted properties are generally easier to read, improve syntax highlighting, and are more easily optimized by many JS engines.
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
3.7 Don’t call Object.prototype methods directly
Do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf.
eslint: no-prototype-builtins
These methods may be shadowed by properties on the object in question — consider { hasOwnProperty: false } — or the object may be a null object (Object.create(null)).
Calling object.hasOwnProperty(key) directly is unsafe. Use Object.prototype.hasOwnProperty.call(object, key) or Object.hasOwn(object, key) instead.
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// better
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(object, key));
// best
console.log(Object.hasOwn(object, key)); // only supported in browsers that support ES2022
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
/* or */
console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown
3.8 Prefer object spread over Object.assign
Prefer the object spread syntax over Object.assign to shallow-copy objects. Use the object rest parameter syntax to get a new object with certain properties omitted.
eslint: prefer-object-spread
Using Object.assign(original, {...}) mutates the original object. Always prefer spread syntax to avoid unintended mutations.
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ
delete copy.a; // so does this
// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
Arrays
4.1 Use literal syntax for array creation
Use the literal syntax for array creation.
eslint: no-array-constructor
const items = new Array();
4.2 Use Array#push to add items
Use Array#push instead of direct assignment to add items to an array.
const someStack = [];
someStack.push('abracadabra');
const someStack = [];
someStack[someStack.length] = 'abracadabra';
4.3 Use spread to copy arrays
Use array spreads ... to copy arrays.
const itemsCopy = [...items];
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}
4.4 Convert iterables to arrays with spread
To convert an iterable object to an array, use spreads ... instead of Array.from.
const foo = document.querySelectorAll('.foo');
// good
const nodes = Array.from(foo);
// best
const nodes = [...foo];
4.5 Convert array-like objects with Array.from
Use Array.from for converting an array-like object to an array.
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
// bad
const arr = Array.prototype.slice.call(arrLike);
// good
const arr = Array.from(arrLike);
4.6 Use Array.from for mapping over iterables
Use Array.from instead of spread ... for mapping over iterables, because it avoids creating an intermediate array.
const baz = Array.from(foo, bar);
const baz = [...foo].map(bar);
4.7 Use return statements in array method callbacks
Use return statements in array method callbacks. It’s ok to omit the return if the function body consists of a single statement returning an expression without side effects.
eslint: array-callback-return
Forgetting a return in a reduce callback causes acc to become undefined after the first iteration, silently corrupting your result.
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => x + 1);
// bad - no returned value means `acc` becomes undefined after the first iteration
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
const flatten = acc.concat(item);
});
// good
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
const flatten = acc.concat(item);
return flatten;
});
// bad
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
} else {
return false;
}
});
// good
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
}
return false;
});
4.8 Use line breaks for multiline arrays
Use line breaks after opening array brackets and before closing array brackets, if an array has multiple lines.
const arr = [[0, 1], [2, 3], [4, 5]];
const objectInArray = [
{
id: 1,
},
{
id: 2,
},
];
const numberInArray = [
1,
2,
];
const arr = [
[0, 1], [2, 3], [4, 5],
];
const objectInArray = [{
id: 1,
}, {
id: 2,
}];
const numberInArray = [
1, 2,
];