diff --git a/README.md b/README.md index 731c54f810..aecd93f949 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Other Style Guides + `undefined` ```javascript + // (es6: let, const) const foo = 1; let bar = foo; @@ -75,6 +76,7 @@ Other Style Guides + `function` ```javascript + // (es6: const) const foo = [1, 2]; const bar = foo; @@ -96,7 +98,7 @@ Other Style Guides var a = 1; var b = 2; - // good + // good (es6: const) const a = 1; const b = 2; ``` @@ -113,6 +115,7 @@ Other Style Guides } // good, use the let. + // (es6: let) let count = 1; if (true) { count += 1; @@ -123,6 +126,7 @@ Other Style Guides ```javascript // const and let only exist in the blocks they are defined in. + // (es6: let, const) { let a = 1; const b = 1; @@ -138,23 +142,23 @@ Other Style Guides - [3.1](#3.1) Use the literal syntax for object creation. ```javascript - // bad + // bad (es6: const) const item = new Object(); - // good + // good (es6: const) const item = {}; ``` - [3.2](#3.2) If your code will be executed in browsers in script context, don't use [reserved words](http://es5.github.io/#x7.6.1) as keys. It won't work in IE8. [More info](https://github.com/airbnb/javascript/issues/61). It’s OK to use them in ES6 modules and server-side code. ```javascript - // bad + // bad (es6: const) const superman = { default: { clark: 'kent' }, private: true, }; - // good + // good (es6: const) const superman = { defaults: { clark: 'kent' }, hidden: true, @@ -164,17 +168,17 @@ Other Style Guides - [3.3](#3.3) Use readable synonyms in place of reserved words. ```javascript - // bad + // bad (es6: const) const superman = { class: 'alien', }; - // bad + // bad (es6: const) const superman = { klass: 'alien', }; - // good + // good (es6: const) const superman = { type: 'alien', }; @@ -188,17 +192,18 @@ Other Style Guides ```javascript function getKey(k) { + // (es6: Template Strings) return `a key named ${k}`; } - // bad + // bad (es6: const) const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; - // good + // good (es6: const, Enhanced Object) const obj = { id: 5, name: 'San Francisco', @@ -210,7 +215,7 @@ Other Style Guides - [3.5](#3.5) Use object method shorthand. ```javascript - // bad + // bad (es6: const, Enhanced Object) const atom = { value: 1, @@ -219,7 +224,7 @@ Other Style Guides }, }; - // good + // good (es6: const, Enhanced Object) const atom = { value: 1, @@ -235,14 +240,15 @@ Other Style Guides > Why? It is shorter to write and descriptive. ```javascript + // (es6: const) const lukeSkywalker = 'Luke Skywalker'; - // bad + // bad (es6: const) const obj = { lukeSkywalker: lukeSkywalker, }; - // good + // good (es6: const, Enhanced Object) const obj = { lukeSkywalker, }; @@ -253,10 +259,11 @@ Other Style Guides > Why? It's easier to tell which properties are using the shorthand. ```javascript + // (es6: const) const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; - // bad + // bad (es6: const, Enhanced Object) const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, @@ -266,7 +273,7 @@ Other Style Guides anakinSkywalker, }; - // good + // good (es6: const, Enhanced Object) const obj = { lukeSkywalker, anakinSkywalker, @@ -284,16 +291,17 @@ Other Style Guides - [4.1](#4.1) Use the literal syntax for array creation. ```javascript - // bad + // bad (es6: const) const items = new Array(); - // good + // good (es6: const) const items = []; ``` - [4.2](#4.2) Use Array#push instead of direct assignment to add items to an array. ```javascript + // (es6: const) const someStack = []; // bad @@ -307,7 +315,7 @@ Other Style Guides - [4.3](#4.3) Use array spreads `...` to copy arrays. ```javascript - // bad + // bad (es6: let, const) const len = items.length; const itemsCopy = []; let i; @@ -316,12 +324,13 @@ Other Style Guides itemsCopy[i] = items[i]; } - // good + // good (es6: const) const itemsCopy = [...items]; ``` - [4.4](#4.4) To convert an array-like object to an array, use Array#from. ```javascript + // (es6: const, Array) const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo); ``` @@ -335,21 +344,20 @@ Other Style Guides > Why? Destructuring saves you from creating temporary references for those properties. ```javascript - // bad + // bad (es6: Template Strings, const) function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; - return `${firstName} ${lastName}`; } - // good + // good (es6: Template Strings, const) function getFullName(obj) { const { firstName, lastName } = obj; return `${firstName} ${lastName}`; } - // best + // best (es6: Template Strings, Destructuring) function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; } @@ -358,13 +366,14 @@ Other Style Guides - [5.2](#5.2) Use array destructuring. ```javascript + // (es6: const) const arr = [1, 2, 3, 4]; - // bad + // bad (es6: const) const first = arr[0]; const second = arr[1]; - // good + // good (es6: const, destructuring) const [first, second] = arr; ``` @@ -380,6 +389,7 @@ Other Style Guides } // the caller needs to think about the order of return data + // (es6: const, destructuring, object matching) const [left, __, top] = processInput(input); // good @@ -389,6 +399,7 @@ Other Style Guides } // the caller selects only the data they need + // (es6: destructuring, object matching) const { left, right } = processInput(input); ``` @@ -400,10 +411,10 @@ Other Style Guides - [6.1](#6.1) Use single quotes `''` for strings. ```javascript - // bad + // bad (es6: const) const name = "Capt. Janeway"; - // good + // good (es6: const) const name = 'Capt. Janeway'; ``` @@ -411,23 +422,23 @@ Other Style Guides - [6.3](#6.3) Note: If overused, long strings with concatenation could impact performance. [jsPerf](http://jsperf.com/ya-string-concat) & [Discussion](https://github.com/airbnb/javascript/issues/40). ```javascript - // bad + // bad (es6: const) const 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 + // bad (es6: const) const 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 + // good (es6: const) const 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.'; ``` - - [6.4](#6.4) When programmatically building up strings, use template strings instead of concatenation. + - [6.4](#6.4) (_es6_: Template Strings) When programmatically building up strings, use template strings instead of concatenation. > Why? Template strings give you a readable, concise syntax with proper newlines and string interpolation features. @@ -444,6 +455,7 @@ Other Style Guides // good function sayHi(name) { + // (es6: Template Strings) return `How are you, ${name}?`; } ``` @@ -459,7 +471,7 @@ Other Style Guides > Why? Function declarations are named, so they're easier to identify in call stacks. Also, the whole body of a function declaration is hoisted, whereas only the reference of a function expression is hoisted. This rule makes it possible to always use [Arrow Functions](#arrow-functions) in place of function expressions. ```javascript - // bad + // bad (es6: const) const foo = function () { }; @@ -471,7 +483,7 @@ Other Style Guides - [7.2](#7.2) Function expressions: ```javascript - // immediately-invoked function expression (IIFE) + // (es6: arrows) immediately-invoked function expression (IIFE) (() => { console.log('Welcome to the Internet. Please follow me.'); })(); @@ -491,6 +503,7 @@ Other Style Guides // good let test; if (currentUser) { + // (es6: arrows) test = () => { console.log('Yup.'); }; @@ -512,7 +525,7 @@ Other Style Guides ``` - - [7.6](#7.6) Never use `arguments`, opt to use rest syntax `...` instead. + - [7.6](#7.6) (es6: Rest) Never use `arguments`, opt to use rest syntax `...` instead. > Why? `...` is explicit about which arguments you want pulled. Plus rest arguments are a real Array and not Array-like like `arguments`. @@ -523,14 +536,14 @@ Other Style Guides return args.join(''); } - // good + // good (es6: Rest) function concatenateAll(...args) { return args.join(''); } ``` - - [7.7](#7.7) Use default parameter syntax rather than mutating function arguments. + - [7.7](#7.7) (es6: Defaults) Use default parameter syntax rather than mutating function arguments. ```javascript // really bad @@ -550,7 +563,7 @@ Other Style Guides // ... } - // good + // good (es6: Defaults) function handleThings(opts = {}) { // ... } @@ -575,12 +588,12 @@ Other Style Guides - [7.9](#7.9) Always put default parameters last. ```javascript - // bad + // bad (es6: Defaults) function handleThings(opts = {}, name) { // ... } - // good + // good (es6: Defaults) function handleThings(name, opts = {}) { // ... } @@ -602,7 +615,7 @@ Other Style Guides ## Arrow Functions - - [8.1](#8.1) When you must use function expressions (as when passing an anonymous function), use arrow function notation. + - [8.1](#8.1) (es6: arrows) When you must use function expressions (as when passing an anonymous function), use arrow function notation. > Why? It creates a version of the function that executes in the context of `this`, which is usually what you want, and is a more concise syntax. @@ -615,7 +628,7 @@ Other Style Guides return x * y; }); - // good + // good (es6: arrows) [1, 2, 3].map((x) => { const y = x + 1; return x * y; @@ -629,16 +642,16 @@ Other Style Guides > Why not? If you plan on returning an object. ```javascript - // good + // good (es6: arrows, Template Strings) [1, 2, 3].map(number => `A string containing the ${number}.`); - // bad + // bad (es6: arrows, Template Strings) [1, 2, 3].map(number => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); - // good + // good (es6: arrows, Template Strings) [1, 2, 3].map(number => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; @@ -650,13 +663,13 @@ Other Style Guides > Why? It shows clearly where the function starts and ends. ```js - // bad + // bad (es6: arrows, Template Strings) [1, 2, 3].map(number => 'As time went by, the string containing the ' + `${number} became much longer. So we needed to break it over multiple ` + 'lines.' ); - // good + // good (es6: arrows, Template Strings) [1, 2, 3].map(number => ( `As time went by, the string containing the ${number} became much ` + 'longer. So we needed to break it over multiple lines.' @@ -669,10 +682,10 @@ Other Style Guides > Why? Less visual clutter. ```js - // good + // good (es6: arrows) [1, 2, 3].map(x => x * x); - // good + // good (es6: arrows) [1, 2, 3].reduce((y, x) => x + y); ``` @@ -681,7 +694,7 @@ Other Style Guides ## Constructors - - [9.1](#9.1) Always use `class`. Avoid manipulating `prototype` directly. + - [9.1](#9.1) (es6: constructor) Always use `class`. Avoid manipulating `prototype` directly. > Why? `class` syntax is more concise and easier to reason about. @@ -699,6 +712,7 @@ Other Style Guides // good class Queue { + // (es6: constructor) constructor(contents = []) { this._queue = [...contents]; } @@ -710,12 +724,12 @@ Other Style Guides } ``` - - [9.2](#9.2) Use `extends` for inheritance. + - [9.2](#9.2) (es6: classes, extends) Use `extends` for inheritance. > Why? It is a built-in way to inherit prototype functionality without breaking `instanceof`. ```javascript - // bad + // bad (es6: const) const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); @@ -725,7 +739,7 @@ Other Style Guides return this._queue[0]; } - // good + // good (es6: classes, extends) class PeekableQueue extends Queue { peek() { return this._queue[0]; @@ -750,7 +764,7 @@ Other Style Guides luke.jump(); // => true luke.setHeight(20); // => undefined - // good + // good (es6: classes) class Jedi { jump() { this.jumping = true; @@ -773,6 +787,7 @@ Other Style Guides - [9.4](#9.4) It's okay to write a custom toString() method, just make sure it works successfully and causes no side effects. ```javascript + // (es6: classes, constructor) class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; @@ -783,6 +798,7 @@ Other Style Guides } toString() { + // (es6: Template Strings) return `Jedi - ${this.getName()}`; } } @@ -793,20 +809,20 @@ Other Style Guides ## Modules - - [10.1](#10.1) Always use modules (`import`/`export`) over a non-standard module system. You can always transpile to your preferred module system. + - [10.1](#10.1) (es6: modules) Always use modules (`import`/`export`) over a non-standard module system. You can always transpile to your preferred module system. > Why? Modules are the future, let's start using the future now. ```javascript - // bad + // bad (es6: modules) const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; - // ok + // ok (es6: modules) import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; - // best + // best (es6: modules) import { es6 } from './AirbnbStyleGuide'; export default es6; ``` @@ -816,10 +832,10 @@ Other Style Guides > Why? This makes sure you have a single default export. ```javascript - // bad + // bad (es6: modules) import * as AirbnbStyleGuide from './AirbnbStyleGuide'; - // good + // good (es6: modules) import AirbnbStyleGuide from './AirbnbStyleGuide'; ``` @@ -828,12 +844,12 @@ Other Style Guides > Why? Although the one-liner is concise, having one clear way to import and one clear way to export makes things consistent. ```javascript - // bad - // filename es6.js + // bad (es6: modules) + // filename es6.js export { es6 as default } from './airbnbStyleGuide'; - // good - // filename es6.js + // good (es6: modules) + // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6; ``` @@ -849,7 +865,7 @@ Other Style Guides ```javascript const numbers = [1, 2, 3, 4, 5]; - // bad + // bad (es6: let) let sum = 0; for (let num of numbers) { sum += num; @@ -857,12 +873,12 @@ Other Style Guides sum === 15; - // good + // good (es6: arrows, let) let sum = 0; numbers.forEach((num) => sum += num); sum === 15; - // best (use the functional force) + // best (use the functional force) (es6: arrows) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; ``` @@ -879,15 +895,16 @@ Other Style Guides - [12.1](#12.1) Use dot notation when accessing properties. ```javascript + // (es6: const) const luke = { jedi: true, age: 28, }; - // bad + // bad (es6: const) const isJedi = luke['jedi']; - // good + // good (es6: const) const isJedi = luke.jedi; ``` @@ -917,7 +934,7 @@ Other Style Guides // bad superPower = new SuperPower(); - // good + // good (es6: const) const superPower = new SuperPower(); ``` @@ -926,7 +943,7 @@ Other Style Guides > Why? It's easier to add new variable declarations this way, and you never have to worry about swapping out a `;` for a `,` or introducing punctuation-only diffs. ```javascript - // bad + // bad (es6: const) const items = getItems(), goSportsTeam = true, dragonball = 'z'; @@ -943,12 +960,12 @@ Other Style Guides const dragonball = 'z'; ``` - - [13.3](#13.3) Group all your `const`s and then group all your `let`s. + - [13.3](#13.3) (es6: let, const) Group all your `const`s and then group all your `let`s. > Why? This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables. ```javascript - // bad + // bad (es6: let) let i, len, dragonball, items = getItems(), goSportsTeam = true; @@ -1251,7 +1268,7 @@ Other Style Guides - [17.2](#17.2) Use `//` for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment. ```javascript - // bad + // bad (es6: const) const active = true; // is current tab // good @@ -1283,6 +1300,7 @@ Other Style Guides - [17.4](#17.4) Use `// FIXME:` to annotate problems. ```javascript + // (es6: classes) class Calculator extends Abacus { constructor() { super(); @@ -1296,6 +1314,7 @@ Other Style Guides - [17.5](#17.5) Use `// TODO:` to annotate solutions to problems. ```javascript + // (es6: classes) class Calculator extends Abacus { constructor() { super(); @@ -1383,7 +1402,7 @@ Other Style Guides - [18.4](#18.4) Set off operators with spaces. ```javascript - // bad + // bad (es6: const) const x=y+5; // good @@ -1437,7 +1456,7 @@ Other Style Guides .find('.open') .updateCount(); - // bad + // bad (es6: const) const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) .attr('width', (radius + margin) * 2).append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') @@ -1470,7 +1489,7 @@ Other Style Guides return baz; - // bad + // bad (es6: const) const obj = { foo() { }, @@ -1490,7 +1509,7 @@ Other Style Guides return obj; - // bad + // bad (es6: const) const arr = [ function foo() { }, @@ -1519,7 +1538,7 @@ Other Style Guides - [19.1](#19.1) Leading commas: **Nope.** ```javascript - // bad + // bad (es6: const) const story = [ once , upon @@ -1533,7 +1552,7 @@ Other Style Guides aTime, ]; - // bad + // bad (es6: const) const hero = { firstName: 'Ada' , lastName: 'Lovelace' @@ -1570,7 +1589,7 @@ Other Style Guides + inventorOf: ['coxcomb chart', 'modern nursing'], }; - // bad + // bad (es6: const) const hero = { firstName: 'Dana', lastName: 'Scully' @@ -1607,13 +1626,13 @@ Other Style Guides return name })() - // good + // good (es6: arrows) (() => { const name = 'Skywalker'; return name; })(); - // good (guards against the function becoming an argument when two files with IIFEs are concatenated) + // good (guards against the function becoming an argument when two files with IIFEs are concatenated) (es6: arrows) ;(() => { const name = 'Skywalker'; return name; @@ -1630,10 +1649,10 @@ Other Style Guides - [21.1](#21.1) Perform type coercion at the beginning of the statement. - [21.2](#21.2) Strings: - ```javascript + ```javascript (es6: arrows) // => this.reviewScore = 9; - // bad + // bad (es6: const) const totalScore = this.reviewScore + ''; // good @@ -1645,16 +1664,16 @@ Other Style Guides ```javascript const inputValue = '4'; - // bad + // bad (es6: const) const val = new Number(inputValue); - // bad + // bad (es6: const) const val = +inputValue; - // bad + // bad (es6: const) const val = inputValue >> 0; - // bad + // bad (es6: const) const val = parseInt(inputValue); // good @@ -1689,7 +1708,7 @@ Other Style Guides ```javascript const age = 0; - // bad + // bad (es6: const) const hasAge = new Boolean(age); // good @@ -1721,7 +1740,7 @@ Other Style Guides - [22.2](#22.2) Use camelCase when naming objects, functions, and instances. ```javascript - // bad + // bad (es6: const) const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} @@ -1785,7 +1804,7 @@ Other Style Guides }; } - // good + // good (es6: arrows) function foo() { return () => { console.log(this); @@ -1795,20 +1814,20 @@ Other Style Guides - [22.6](#22.6) If your file exports a single class, your filename should be exactly the name of the class. ```javascript - // file contents + // file contents (es6: modules) class CheckBox { // ... } export default CheckBox; // in some other file - // bad + // bad (es6: modules) import CheckBox from './checkBox'; - // bad + // bad (es6: modules) import CheckBox from './check_box'; - // good + // good (es6: modules) import CheckBox from './CheckBox'; ``` @@ -1817,7 +1836,7 @@ Other Style Guides ```javascript function makeStyleGuide() { } - + // (es6: modules) export default makeStyleGuide; ``` @@ -1828,7 +1847,7 @@ Other Style Guides es6: { } }; - + // (es6: modules) export default AirbnbStyleGuide; ``` @@ -1927,7 +1946,7 @@ Other Style Guides - [25.1](#25.1) Prefix jQuery object variables with a `$`. ```javascript - // bad + // bad (es6: const) const sidebar = $('.sidebar'); // good