Last active
February 20, 2021 19:07
-
-
Save nchDev-js/72d8fb8dbf8d6a837a4cead9b50ae997 to your computer and use it in GitHub Desktop.
AIRBNB_good_vs_bad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use computed property names when creating objects with dynamic property names. | |
| function getKey(k) { | |
| return `a key named ${k}`; | |
| } | |
| // bad | |
| const obj = { | |
| id: 5, | |
| name: 'San Francisco', | |
| }; | |
| obj[getKey('enabled')] = true; | |
| // good | |
| const obj = { | |
| id: 5, | |
| name: 'San Francisco', | |
| [getKey('enabled')]: true, | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use object method shorthand | |
| // bad | |
| const atom = { | |
| value: 1, | |
| addValue: function (value) { | |
| return atom.value + value; | |
| }, | |
| }; | |
| // good | |
| const atom = { | |
| value: 1, | |
| addValue(value) { | |
| return atom.value + value; | |
| }, | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf. | |
| // bad | |
| console.log(object.hasOwnProperty(key)); | |
| // good | |
| console.log(Object.prototype.hasOwnProperty.call(object, key)); | |
| // best | |
| const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. | |
| console.log(has.call(object, key)); | |
| /* or */ | |
| import has from 'has'; // https://www.npmjs.com/package/has | |
| console.log(has(object, key)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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 } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // bad | |
| function getFullName(user) { | |
| const firstName = user.firstName; | |
| const lastName = user.lastName; | |
| return `${firstName} ${lastName}`; | |
| } | |
| // good | |
| function getFullName(user) { | |
| const { firstName, lastName } = user; | |
| return `${firstName} ${lastName}`; | |
| } | |
| // best | |
| function getFullName({ firstName, lastName }) { | |
| return `${firstName} ${lastName}`; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use object destructuring for multiple return values, not array destructuring. | |
| // bad | |
| function processInput(input) { | |
| // then a miracle occurs | |
| return [left, right, top, bottom]; | |
| } | |
| // the caller needs to think about the order of return data | |
| const [left, __, top] = processInput(input); | |
| // good | |
| function processInput(input) { | |
| // then a miracle occurs | |
| return { left, right, top, bottom }; | |
| } | |
| // the caller selects only the data they need | |
| const { left, top } = processInput(input); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // bad | |
| const foo = '\'this\' \i\s \"quoted\"'; | |
| // good | |
| const foo = '\'this\' is "quoted"'; | |
| const foo = `my name is '${name}'`; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // note: ECMA-262 defines a block as a list of statements. A function declaration is not a statement. | |
| // bad | |
| if (currentUser) { | |
| function test() { | |
| console.log('Nope.'); | |
| } | |
| } | |
| // good | |
| let test; | |
| if (currentUser) { | |
| test = () => { | |
| console.log('Yup.'); | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // never use arguments, opt to use rest syntax ... instead | |
| // bad | |
| function concatenateAll() { | |
| const args = Array.prototype.slice.call(arguments); | |
| return args.join(''); | |
| } | |
| // good | |
| function concatenateAll(...args) { | |
| return args.join(''); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // really bad | |
| function handleThings(opts) { | |
| // No! We shouldn’t mutate function arguments. | |
| // Double bad: if opts is falsy it'll be set to an object which may | |
| // be what you want but it can introduce subtle bugs. | |
| opts = opts || {}; | |
| // ... | |
| } | |
| // still bad | |
| function handleThings(opts) { | |
| if (opts === void 0) { | |
| opts = {}; | |
| } | |
| // ... | |
| } | |
| // good | |
| function handleThings(opts = {}) { | |
| // ... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // always put default parameters last | |
| // bad | |
| function handleThings(opts = {}, name) { | |
| // ... | |
| } | |
| // good | |
| function handleThings(name, opts = {}) { | |
| // ... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // spacing in a function signature | |
| // bad | |
| const f = function(){}; | |
| const g = function (){}; | |
| const h = function() {}; | |
| // good | |
| const x = function () {}; | |
| const y = function a() {}; | |
| // place no space between the argument list and the function name in function calls and declarations. | |
| // bad | |
| function fight () { | |
| console.log ('Swooosh!'); | |
| } | |
| // good | |
| function fight() { | |
| console.log('Swooosh!'); | |
| } | |
| // place 1 space before the leading brace. | |
| // bad | |
| function test(){ | |
| console.log('test'); | |
| } | |
| // good | |
| function test() { | |
| console.log('test'); | |
| } | |
| // place 1 space before the opening parenthesis in control statements (if, while etc.). | |
| // bad | |
| if(isJedi) { | |
| fight (); | |
| } | |
| // good | |
| if (isJedi) { | |
| fight(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // never mutate parameters | |
| // bad | |
| function f1(obj) { | |
| obj.key = 1; | |
| } | |
| // good | |
| function f2(obj) { | |
| const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; | |
| } | |
| //never reassign parameters | |
| // bad | |
| function f1(a) { | |
| a = 1; | |
| // ... | |
| } | |
| function f2(a) { | |
| if (!a) { a = 1; } | |
| // ... | |
| } | |
| // good | |
| function f3(a) { | |
| const b = a || 1; | |
| // ... | |
| } | |
| function f4(a = 1) { | |
| // ... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // If the function body consists of a single statement returning an expression without side effects, | |
| // omit the braces and use the implicit return. Otherwise, keep the braces and use a return statement. | |
| // No implicit return with side effects | |
| function foo(callback) { | |
| const val = callback(); | |
| if (val === true) { | |
| // Do something if callback returns true | |
| } | |
| } | |
| let bool = false; | |
| // bad | |
| foo(() => bool = true); | |
| // good | |
| foo(() => { | |
| bool = true; | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // methods can return this to help with method chaining. | |
| // bad | |
| Jedi.prototype.jump = function () { | |
| this.jumping = true; | |
| return true; | |
| }; | |
| Jedi.prototype.setHeight = function (height) { | |
| this.height = height; | |
| }; | |
| const luke = new Jedi(); | |
| luke.jump(); // => true | |
| luke.setHeight(20); // => undefined | |
| // good | |
| class Jedi { | |
| jump() { | |
| this.jumping = true; | |
| return this; | |
| } | |
| setHeight(height) { | |
| this.height = height; | |
| return this; | |
| } | |
| } | |
| const luke = new Jedi(); | |
| luke.jump() | |
| .setHeight(20); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Class methods should use this or be made into a static method unless an external library | |
| // or framework requires to use specific non-static methods. | |
| // bad | |
| class Foo { | |
| bar() { | |
| console.log('bar'); | |
| } | |
| } | |
| // good - this is used | |
| class Foo { | |
| bar() { | |
| console.log(this.bar); | |
| } | |
| } | |
| // good - constructor is exempt | |
| class Foo { | |
| constructor() { | |
| // ... | |
| } | |
| } | |
| // good - static methods aren't expected to use this | |
| class Foo { | |
| static bar() { | |
| console.log('bar'); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // do not use JavaScript getters/setters as they cause unexpected side effects and are harder to test, | |
| // maintain, and reason about. | |
| // bad | |
| class Dragon { | |
| get age() { | |
| // ... | |
| } | |
| set age(value) { | |
| // ... | |
| } | |
| } | |
| // good | |
| class Dragon { | |
| getAge() { | |
| // ... | |
| } | |
| setAge(value) { | |
| // ... | |
| } | |
| } | |
| // it’s okay to create get() and set() functions, but be consistent. | |
| class Jedi { | |
| constructor(options = {}) { | |
| const lightsaber = options.lightsaber || 'blue'; | |
| this.set('lightsaber', lightsaber); | |
| } | |
| set(key, val) { | |
| this[key] = val; | |
| } | |
| get(key) { | |
| return this[key]; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // do not export mutable bindings | |
| // bad | |
| let foo = 3; | |
| export { foo }; | |
| // good | |
| const foo = 3; | |
| export { foo }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use dot notation when accessing properties. | |
| const luke = { | |
| jedi: true, | |
| age: 28, | |
| }; | |
| // bad | |
| const isJedi = luke['jedi']; | |
| // good | |
| const isJedi = luke.jedi; | |
| // use bracket notation [] when accessing properties with a variable. | |
| const luke = { | |
| jedi: true, | |
| age: 28, | |
| }; | |
| function getProp(prop) { | |
| return luke[prop]; | |
| } | |
| const isJedi = getProp('jedi'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ternaries should not be nested and generally be single line expressions. eslint: no-nested-ternary | |
| // bad | |
| const foo = maybe1 > maybe2 | |
| ? "bar" | |
| : value1 > value2 ? "baz" : null; | |
| // split into 2 separated ternary expressions | |
| const maybeNull = value1 > value2 ? 'baz' : null; | |
| // better | |
| const foo = maybe1 > maybe2 | |
| ? 'bar' | |
| : maybeNull; | |
| // best | |
| const foo = maybe1 > maybe2 ? 'bar' : maybeNull; | |
| //avoid unneeded ternary statements | |
| // bad | |
| const foo = a ? a : b; | |
| const bar = c ? true : false; | |
| const baz = c ? false : true; | |
| // good | |
| const foo = a || b; | |
| const bar = !!c; | |
| const baz = !c; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // anonymous function expressions hoist their variable name, but not the function assignment. | |
| function example() { | |
| console.log(anonymous); // => undefined | |
| anonymous(); // => TypeError anonymous is not a function | |
| var anonymous = function () { | |
| console.log('anonymous function expression'); | |
| }; | |
| } | |
| // named function expressions hoist the variable name, not the function name or the function body. | |
| function example() { | |
| console.log(named); // => undefined | |
| named(); // => TypeError named is not a function | |
| superPower(); // => ReferenceError superPower is not defined | |
| var named = function superPower() { | |
| console.log('Flying'); | |
| }; | |
| } | |
| // the same is true when the function name is the same as the variable name. | |
| function example() { | |
| console.log(named); // => undefined | |
| named(); // => TypeError named is not a function | |
| var named = function named() { | |
| console.log('named'); | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use shortcuts for booleans, but explicit comparisons for strings and numbers. | |
| // bad | |
| if (isValid === true) { | |
| // ... | |
| } | |
| // good | |
| if (isValid) { | |
| // ... | |
| } | |
| // bad | |
| if (name) { | |
| // ... | |
| } | |
| // good | |
| if (name !== '') { | |
| // ... | |
| } | |
| // bad | |
| if (collection.length) { | |
| // ... | |
| } | |
| // good | |
| if (collection.length > 0) { | |
| // ... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // use braces to create blocks in case and default clauses that contain lexical declarations | |
| // (e.g. let, const, function, and class). | |
| // bad | |
| switch (foo) { | |
| case 1: | |
| let x = 1; | |
| break; | |
| case 2: | |
| const y = 2; | |
| break; | |
| case 3: | |
| function f() { | |
| // ... | |
| } | |
| break; | |
| default: | |
| class C {} | |
| } | |
| // good | |
| switch (foo) { | |
| case 1: { | |
| let x = 1; | |
| break; | |
| } | |
| case 2: { | |
| const y = 2; | |
| break; | |
| } | |
| case 3: { | |
| function f() { | |
| // ... | |
| } | |
| break; | |
| } | |
| case 4: | |
| bar(); | |
| break; | |
| default: { | |
| class C {} | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // STRING | |
| // => this.reviewScore = 9; | |
| const totalScore = String(this.reviewScore); | |
| // NUMBER | |
| const inputValue = '4'; | |
| const val = Number(inputValue); | |
| //or | |
| const val = parseInt(inputValue, 10); | |
| // BOOLEAN | |
| const age = 0; | |
| const hasAge = Boolean(age); | |
| // or best | |
| const hasAge = !!age; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // bad | |
| const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file'; | |
| // bad | |
| export const THING_TO_BE_CHANGED = 'should obviously not be uppercased'; | |
| // bad | |
| export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables'; | |
| // --- | |
| // allowed but does not supply semantic value | |
| export const apiKey = 'SOMEKEY'; | |
| // better in most cases | |
| export const API_KEY = 'SOMEKEY'; | |
| // --- | |
| // bad - unnecessarily uppercases key while adding no semantic value | |
| export const MAPPING = { | |
| KEY: 'value' | |
| }; | |
| // good | |
| export const MAPPING = { | |
| key: 'value' | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment