[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-280":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":23,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":38,"readmeContent":39,"aiSummary":40,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":41,"discoverSource":42},280,"javascript","airbnb\u002Fjavascript","airbnb","JavaScript Style Guide",null,"JavaScript",148082,26647,3665,100,0,2,25,1,73.5,"MIT License",false,"master",true,[25,26,27,28,29,30,31,5,32,33,34,35,36,37],"arrow-functions","es2015","es2016","es2017","es2018","es6","eslint","linting","naming-conventions","style-guide","style-linter","styleguide","tc39","2026-06-17 04:00:02","# Airbnb JavaScript Style Guide() {\n\n*A mostly reasonable approach to JavaScript*\n\n> **Note**: this guide assumes you are using [Babel](https:\u002F\u002Fbabeljs.io), and requires that you use [babel-preset-airbnb](https:\u002F\u002Fnpmjs.com\u002Fbabel-preset-airbnb) or the equivalent. It also assumes you are installing shims\u002Fpolyfills in your app, with [airbnb-browser-shims](https:\u002F\u002Fnpmjs.com\u002Fairbnb-browser-shims) or the equivalent.\n\n[![Downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002Feslint-config-airbnb.svg)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Feslint-config-airbnb)\n[![Downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002Feslint-config-airbnb-base.svg)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Feslint-config-airbnb-base)\n[![Gitter](https:\u002F\u002Fbadges.gitter.im\u002FJoin%20Chat.svg)](https:\u002F\u002Fgitter.im\u002Fairbnb\u002Fjavascript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)\n\nThis guide is available in other languages too. See [Translation](#translation)\n\nOther Style Guides\n\n  - [ES5 (Deprecated)](https:\u002F\u002Fgithub.com\u002Fairbnb\u002Fjavascript\u002Ftree\u002Fes5-deprecated\u002Fes5)\n  - [React](react\u002F)\n  - [CSS-in-JavaScript](css-in-javascript\u002F)\n  - [CSS & Sass](https:\u002F\u002Fgithub.com\u002Fairbnb\u002Fcss)\n  - [Ruby](https:\u002F\u002Fgithub.com\u002Fairbnb\u002Fruby)\n\n## Table of Contents\n\n  1. [Types](#types)\n  1. [References](#references)\n  1. [Objects](#objects)\n  1. [Arrays](#arrays)\n  1. [Destructuring](#destructuring)\n  1. [Strings](#strings)\n  1. [Functions](#functions)\n  1. [Arrow Functions](#arrow-functions)\n  1. [Classes & Constructors](#classes--constructors)\n  1. [Modules](#modules)\n  1. [Iterators and Generators](#iterators-and-generators)\n  1. [Properties](#properties)\n  1. [Variables](#variables)\n  1. [Hoisting](#hoisting)\n  1. [Comparison Operators & Equality](#comparison-operators--equality)\n  1. [Blocks](#blocks)\n  1. [Control Statements](#control-statements)\n  1. [Comments](#comments)\n  1. [Whitespace](#whitespace)\n  1. [Commas](#commas)\n  1. [Semicolons](#semicolons)\n  1. [Type Casting & Coercion](#type-casting--coercion)\n  1. [Naming Conventions](#naming-conventions)\n  1. [Accessors](#accessors)\n  1. [Events](#events)\n  1. [jQuery](#jquery)\n  1. [ECMAScript 5 Compatibility](#ecmascript-5-compatibility)\n  1. [ECMAScript 6+ (ES 2015+) Styles](#ecmascript-6-es-2015-styles)\n  1. [Standard Library](#standard-library)\n  1. [Testing](#testing)\n  1. [Performance](#performance)\n  1. [Resources](#resources)\n  1. [In the Wild](#in-the-wild)\n  1. [Translation](#translation)\n  1. [The JavaScript Style Guide Guide](#the-javascript-style-guide-guide)\n  1. [Chat With Us About JavaScript](#chat-with-us-about-javascript)\n  1. [Contributors](#contributors)\n  1. [License](#license)\n  1. [Amendments](#amendments)\n\n## Types\n\n  \u003Ca name=\"types--primitives\">\u003C\u002Fa>\u003Ca name=\"1.1\">\u003C\u002Fa>\n  - [1.1](#types--primitives) **Primitives**: When you access a primitive type you work directly on its value.\n\n    - `string`\n    - `number`\n    - `boolean`\n    - `null`\n    - `undefined`\n    - `symbol`\n    - `bigint`\n\n    \u003Cbr \u002F>\n\n    ```javascript\n    const foo = 1;\n    let bar = foo;\n\n    bar = 9;\n\n    console.log(foo, bar); \u002F\u002F => 1, 9\n    ```\n\n    - Symbols and BigInts cannot be faithfully polyfilled, so they should not be used when targeting browsers\u002Fenvironments that don’t support them natively.\n\n  \u003Ca name=\"types--complex\">\u003C\u002Fa>\u003Ca name=\"1.2\">\u003C\u002Fa>\n  - [1.2](#types--complex)  **Complex**: When you access a complex type you work on a reference to its value.\n\n    - `object`\n    - `array`\n    - `function`\n\n    \u003Cbr \u002F>\n\n    ```javascript\n    const foo = [1, 2];\n    const bar = foo;\n\n    bar[0] = 9;\n\n    console.log(foo[0], bar[0]); \u002F\u002F => 9, 9\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## References\n\n  \u003Ca name=\"references--prefer-const\">\u003C\u002Fa>\u003Ca name=\"2.1\">\u003C\u002Fa>\n  - [2.1](#references--prefer-const) Use `const` for all of your references; avoid using `var`. eslint: [`prefer-const`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-const), [`no-const-assign`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-const-assign)\n\n    > Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code.\n\n    ```javascript\n    \u002F\u002F bad\n    var a = 1;\n    var b = 2;\n\n    \u002F\u002F good\n    const a = 1;\n    const b = 2;\n    ```\n\n  \u003Ca name=\"references--disallow-var\">\u003C\u002Fa>\u003Ca name=\"2.2\">\u003C\u002Fa>\n  - [2.2](#references--disallow-var) If you must reassign references, use `let` instead of `var`. eslint: [`no-var`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-var)\n\n    > Why? `let` is block-scoped rather than function-scoped like `var`.\n\n    ```javascript\n    \u002F\u002F bad\n    var count = 1;\n    if (true) {\n      count += 1;\n    }\n\n    \u002F\u002F good, use the let.\n    let count = 1;\n    if (true) {\n      count += 1;\n    }\n    ```\n\n  \u003Ca name=\"references--block-scope\">\u003C\u002Fa>\u003Ca name=\"2.3\">\u003C\u002Fa>\n  - [2.3](#references--block-scope) Note that both `let` and `const` are block-scoped, whereas `var` is function-scoped.\n\n    ```javascript\n    \u002F\u002F const and let only exist in the blocks they are defined in.\n    {\n      let a = 1;\n      const b = 1;\n      var c = 1;\n    }\n    console.log(a); \u002F\u002F ReferenceError\n    console.log(b); \u002F\u002F ReferenceError\n    console.log(c); \u002F\u002F Prints 1\n    ```\n\n    In the above code, you can see that referencing `a` and `b` will produce a ReferenceError, while `c` contains the number. This is because `a` and `b` are block scoped, while `c` is scoped to the containing function.\n\n**[⬆ back to top](#table-of-contents)**\n\n## Objects\n\n  \u003Ca name=\"objects--no-new\">\u003C\u002Fa>\u003Ca name=\"3.1\">\u003C\u002Fa>\n  - [3.1](#objects--no-new) Use the literal syntax for object creation. eslint: [`no-new-object`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-new-object)\n\n    ```javascript\n    \u002F\u002F bad\n    const item = new Object();\n\n    \u002F\u002F good\n    const item = {};\n    ```\n\n  \u003Ca name=\"es6-computed-properties\">\u003C\u002Fa>\u003Ca name=\"3.4\">\u003C\u002Fa>\n  - [3.2](#es6-computed-properties) Use computed property names when creating objects with dynamic property names.\n\n    > Why? They allow you to define all the properties of an object in one place.\n\n    ```javascript\n\n    function getKey(k) {\n      return `a key named ${k}`;\n    }\n\n    \u002F\u002F bad\n    const obj = {\n      id: 5,\n      name: 'San Francisco',\n    };\n    obj[getKey('enabled')] = true;\n\n    \u002F\u002F good\n    const obj = {\n      id: 5,\n      name: 'San Francisco',\n      [getKey('enabled')]: true,\n    };\n    ```\n\n  \u003Ca name=\"es6-object-shorthand\">\u003C\u002Fa>\u003Ca name=\"3.5\">\u003C\u002Fa>\n  - [3.3](#es6-object-shorthand) Use object method shorthand. eslint: [`object-shorthand`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fobject-shorthand)\n\n    ```javascript\n    \u002F\u002F bad\n    const atom = {\n      value: 1,\n\n      addValue: function (value) {\n        return atom.value + value;\n      },\n    };\n\n    \u002F\u002F good\n    const atom = {\n      value: 1,\n\n      addValue(value) {\n        return atom.value + value;\n      },\n    };\n    ```\n\n  \u003Ca name=\"es6-object-concise\">\u003C\u002Fa>\u003Ca name=\"3.6\">\u003C\u002Fa>\n  - [3.4](#es6-object-concise) Use property value shorthand. eslint: [`object-shorthand`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fobject-shorthand)\n\n    > Why? It is shorter and descriptive.\n\n    ```javascript\n    const lukeSkywalker = 'Luke Skywalker';\n\n    \u002F\u002F bad\n    const obj = {\n      lukeSkywalker: lukeSkywalker,\n    };\n\n    \u002F\u002F good\n    const obj = {\n      lukeSkywalker,\n    };\n    ```\n\n  \u003Ca name=\"objects--grouped-shorthand\">\u003C\u002Fa>\u003Ca name=\"3.7\">\u003C\u002Fa>\n  - [3.5](#objects--grouped-shorthand) Group your shorthand properties at the beginning of your object declaration.\n\n    > Why? It’s easier to tell which properties are using the shorthand.\n\n    ```javascript\n    const anakinSkywalker = 'Anakin Skywalker';\n    const lukeSkywalker = 'Luke Skywalker';\n\n    \u002F\u002F bad\n    const obj = {\n      episodeOne: 1,\n      twoJediWalkIntoACantina: 2,\n      lukeSkywalker,\n      episodeThree: 3,\n      mayTheFourth: 4,\n      anakinSkywalker,\n    };\n\n    \u002F\u002F good\n    const obj = {\n      lukeSkywalker,\n      anakinSkywalker,\n      episodeOne: 1,\n      twoJediWalkIntoACantina: 2,\n      episodeThree: 3,\n      mayTheFourth: 4,\n    };\n    ```\n\n  \u003Ca name=\"objects--quoted-props\">\u003C\u002Fa>\u003Ca name=\"3.8\">\u003C\u002Fa>\n  - [3.6](#objects--quoted-props) Only quote properties that are invalid identifiers. eslint: [`quote-props`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fquote-props)\n\n    > Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.\n\n    ```javascript\n    \u002F\u002F bad\n    const bad = {\n      'foo': 3,\n      'bar': 4,\n      'data-blah': 5,\n    };\n\n    \u002F\u002F good\n    const good = {\n      foo: 3,\n      bar: 4,\n      'data-blah': 5,\n    };\n    ```\n\n  \u003Ca name=\"objects--prototype-builtins\">\u003C\u002Fa>\n  - [3.7](#objects--prototype-builtins) Do not call `Object.prototype` methods directly, such as `hasOwnProperty`, `propertyIsEnumerable`, and `isPrototypeOf`. eslint: [`no-prototype-builtins`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-prototype-builtins)\n\n    > Why? 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)`). In modern browsers that support ES2022, or with a polyfill such as \u003Chttps:\u002F\u002Fnpmjs.com\u002Fobject.hasown>, `Object.hasOwn` can also be used as an alternative to `Object.prototype.hasOwnProperty.call`.\n\n    ```javascript\n    \u002F\u002F bad\n    console.log(object.hasOwnProperty(key));\n\n    \u002F\u002F good\n    console.log(Object.prototype.hasOwnProperty.call(object, key));\n\n    \u002F\u002F better\n    const has = Object.prototype.hasOwnProperty; \u002F\u002F cache the lookup once, in module scope.\n    console.log(has.call(object, key));\n\n    \u002F\u002F best\n    console.log(Object.hasOwn(object, key)); \u002F\u002F only supported in browsers that support ES2022\n\n    \u002F* or *\u002F\n    import has from 'has'; \u002F\u002F https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fhas\n    console.log(has(object, key));\n    \u002F* or *\u002F\n    console.log(Object.hasOwn(object, key)); \u002F\u002F https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fobject.hasown\n    ```\n\n  \u003Ca name=\"objects--rest-spread\">\u003C\u002Fa>\n  - [3.8](#objects--rest-spread) Prefer the object spread syntax over [`Object.assign`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FObject\u002Fassign) to shallow-copy objects. Use the object rest parameter syntax to get a new object with certain properties omitted. eslint: [`prefer-object-spread`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-object-spread)\n\n    ```javascript\n    \u002F\u002F very bad\n    const original = { a: 1, b: 2 };\n    const copy = Object.assign(original, { c: 3 }); \u002F\u002F this mutates `original` ಠ_ಠ\n    delete copy.a; \u002F\u002F so does this\n\n    \u002F\u002F bad\n    const original = { a: 1, b: 2 };\n    const copy = Object.assign({}, original, { c: 3 }); \u002F\u002F copy => { a: 1, b: 2, c: 3 }\n\n    \u002F\u002F good\n    const original = { a: 1, b: 2 };\n    const copy = { ...original, c: 3 }; \u002F\u002F copy => { a: 1, b: 2, c: 3 }\n\n    const { a, ...noA } = copy; \u002F\u002F noA => { b: 2, c: 3 }\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Arrays\n\n  \u003Ca name=\"arrays--literals\">\u003C\u002Fa>\u003Ca name=\"4.1\">\u003C\u002Fa>\n  - [4.1](#arrays--literals) Use the literal syntax for array creation. eslint: [`no-array-constructor`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-array-constructor)\n\n    ```javascript\n    \u002F\u002F bad\n    const items = new Array();\n\n    \u002F\u002F good\n    const items = [];\n    ```\n\n  \u003Ca name=\"arrays--push\">\u003C\u002Fa>\u003Ca name=\"4.2\">\u003C\u002Fa>\n  - [4.2](#arrays--push) Use [Array#push](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002Fpush) instead of direct assignment to add items to an array.\n\n    ```javascript\n    const someStack = [];\n\n    \u002F\u002F bad\n    someStack[someStack.length] = 'abracadabra';\n\n    \u002F\u002F good\n    someStack.push('abracadabra');\n    ```\n\n  \u003Ca name=\"es6-array-spreads\">\u003C\u002Fa>\u003Ca name=\"4.3\">\u003C\u002Fa>\n  - [4.3](#es6-array-spreads) Use array spreads `...` to copy arrays.\n\n    ```javascript\n    \u002F\u002F bad\n    const len = items.length;\n    const itemsCopy = [];\n    let i;\n\n    for (i = 0; i \u003C len; i += 1) {\n      itemsCopy[i] = items[i];\n    }\n\n    \u002F\u002F good\n    const itemsCopy = [...items];\n    ```\n\n  \u003Ca name=\"arrays--from\">\u003C\u002Fa>\n  \u003Ca name=\"arrays--from-iterable\">\u003C\u002Fa>\u003Ca name=\"4.4\">\u003C\u002Fa>\n  - [4.4](#arrays--from-iterable) To convert an iterable object to an array, use spreads `...` instead of [`Array.from`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002Ffrom)\n\n    ```javascript\n    const foo = document.querySelectorAll('.foo');\n\n    \u002F\u002F good\n    const nodes = Array.from(foo);\n\n    \u002F\u002F best\n    const nodes = [...foo];\n    ```\n\n  \u003Ca name=\"arrays--from-array-like\">\u003C\u002Fa>\n  - [4.5](#arrays--from-array-like) Use [`Array.from`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002Ffrom) for converting an array-like object to an array.\n\n    ```javascript\n    const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };\n\n    \u002F\u002F bad\n    const arr = Array.prototype.slice.call(arrLike);\n\n    \u002F\u002F good\n    const arr = Array.from(arrLike);\n    ```\n\n  \u003Ca name=\"arrays--mapping\">\u003C\u002Fa>\n  - [4.6](#arrays--mapping) Use [`Array.from`](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002Ffrom) instead of spread `...` for mapping over iterables, because it avoids creating an intermediate array.\n\n    ```javascript\n    \u002F\u002F bad\n    const baz = [...foo].map(bar);\n\n    \u002F\u002F good\n    const baz = Array.from(foo, bar);\n    ```\n\n  \u003Ca name=\"arrays--callback-return\">\u003C\u002Fa>\u003Ca name=\"4.5\">\u003C\u002Fa>\n  - [4.7](#arrays--callback-return) 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, following [8.2](#arrows--implicit-return). eslint: [`array-callback-return`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Farray-callback-return)\n\n    ```javascript\n    \u002F\u002F good\n    [1, 2, 3].map((x) => {\n      const y = x + 1;\n      return x * y;\n    });\n\n    \u002F\u002F good\n    [1, 2, 3].map((x) => x + 1);\n\n    \u002F\u002F bad - no returned value means `acc` becomes undefined after the first iteration\n    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {\n      const flatten = acc.concat(item);\n    });\n\n    \u002F\u002F good\n    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {\n      const flatten = acc.concat(item);\n      return flatten;\n    });\n\n    \u002F\u002F bad\n    inbox.filter((msg) => {\n      const { subject, author } = msg;\n      if (subject === 'Mockingbird') {\n        return author === 'Harper Lee';\n      } else {\n        return false;\n      }\n    });\n\n    \u002F\u002F good\n    inbox.filter((msg) => {\n      const { subject, author } = msg;\n      if (subject === 'Mockingbird') {\n        return author === 'Harper Lee';\n      }\n\n      return false;\n    });\n    ```\n\n  \u003Ca name=\"arrays--bracket-newline\">\u003C\u002Fa>\n  - [4.8](#arrays--bracket-newline) Use line breaks after opening array brackets and before closing array brackets, if an array has multiple lines\n\n    ```javascript\n    \u002F\u002F bad\n    const arr = [\n      [0, 1], [2, 3], [4, 5],\n    ];\n\n    const objectInArray = [{\n      id: 1,\n    }, {\n      id: 2,\n    }];\n\n    const numberInArray = [\n      1, 2,\n    ];\n\n    \u002F\u002F good\n    const arr = [[0, 1], [2, 3], [4, 5]];\n\n    const objectInArray = [\n      {\n        id: 1,\n      },\n      {\n        id: 2,\n      },\n    ];\n\n    const numberInArray = [\n      1,\n      2,\n    ];\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Destructuring\n\n  \u003Ca name=\"destructuring--object\">\u003C\u002Fa>\u003Ca name=\"5.1\">\u003C\u002Fa>\n  - [5.1](#destructuring--object) Use object destructuring when accessing and using multiple properties of an object. eslint: [`prefer-destructuring`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-destructuring)\n\n    > Why? Destructuring saves you from creating temporary references for those properties, and from repetitive access of the object. Repeating object access creates more repetitive code, requires more reading, and creates more opportunities for mistakes. Destructuring objects also provides a single site of definition of the object structure that is used in the block, rather than requiring reading the entire block to determine what is used.\n\n    ```javascript\n    \u002F\u002F bad\n    function getFullName(user) {\n      const firstName = user.firstName;\n      const lastName = user.lastName;\n\n      return `${firstName} ${lastName}`;\n    }\n\n    \u002F\u002F good\n    function getFullName(user) {\n      const { firstName, lastName } = user;\n      return `${firstName} ${lastName}`;\n    }\n\n    \u002F\u002F best\n    function getFullName({ firstName, lastName }) {\n      return `${firstName} ${lastName}`;\n    }\n    ```\n\n  \u003Ca name=\"destructuring--array\">\u003C\u002Fa>\u003Ca name=\"5.2\">\u003C\u002Fa>\n  - [5.2](#destructuring--array) Use array destructuring. eslint: [`prefer-destructuring`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-destructuring)\n\n    ```javascript\n    const arr = [1, 2, 3, 4];\n\n    \u002F\u002F bad\n    const first = arr[0];\n    const second = arr[1];\n\n    \u002F\u002F good\n    const [first, second] = arr;\n    ```\n\n  \u003Ca name=\"destructuring--object-over-array\">\u003C\u002Fa>\u003Ca name=\"5.3\">\u003C\u002Fa>\n  - [5.3](#destructuring--object-over-array) Use object destructuring for multiple return values, not array destructuring.\n\n    > Why? You can add new properties over time or change the order of things without breaking call sites.\n\n    ```javascript\n    \u002F\u002F bad\n    function processInput(input) {\n      \u002F\u002F then a miracle occurs\n      return [left, right, top, bottom];\n    }\n\n    \u002F\u002F the caller needs to think about the order of return data\n    const [left, __, top] = processInput(input);\n\n    \u002F\u002F good\n    function processInput(input) {\n      \u002F\u002F then a miracle occurs\n      return { left, right, top, bottom };\n    }\n\n    \u002F\u002F the caller selects only the data they need\n    const { left, top } = processInput(input);\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Strings\n\n  \u003Ca name=\"strings--quotes\">\u003C\u002Fa>\u003Ca name=\"6.1\">\u003C\u002Fa>\n  - [6.1](#strings--quotes) Use single quotes `''` for strings. eslint: [`quotes`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fquotes)\n\n    ```javascript\n    \u002F\u002F bad\n    const name = \"Capt. Janeway\";\n\n    \u002F\u002F bad - template literals should contain interpolation or newlines\n    const name = `Capt. Janeway`;\n\n    \u002F\u002F good\n    const name = 'Capt. Janeway';\n    ```\n\n  \u003Ca name=\"strings--line-length\">\u003C\u002Fa>\u003Ca name=\"6.2\">\u003C\u002Fa>\n  - [6.2](#strings--line-length) Strings that cause the line to go over 100 characters should not be written across multiple lines using string concatenation.\n\n    > Why? Broken strings are painful to work with and make code less searchable.\n\n    ```javascript\n    \u002F\u002F bad\n    const errorMessage = 'This is a super long error that was thrown because \\\n    of Batman. When you stop to think about how Batman had anything to do \\\n    with this, you would get nowhere \\\n    fast.';\n\n    \u002F\u002F bad\n    const errorMessage = 'This is a super long error that was thrown because ' +\n      'of Batman. When you stop to think about how Batman had anything to do ' +\n      'with this, you would get nowhere fast.';\n\n    \u002F\u002F good\n    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.';\n    ```\n\n  \u003Ca name=\"es6-template-literals\">\u003C\u002Fa>\u003Ca name=\"6.4\">\u003C\u002Fa>\n  - [6.3](#es6-template-literals) When programmatically building up strings, use template strings instead of concatenation. eslint: [`prefer-template`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-template) [`template-curly-spacing`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Ftemplate-curly-spacing)\n\n    > Why? Template strings give you a readable, concise syntax with proper newlines and string interpolation features.\n\n    ```javascript\n    \u002F\u002F bad\n    function sayHi(name) {\n      return 'How are you, ' + name + '?';\n    }\n\n    \u002F\u002F bad\n    function sayHi(name) {\n      return ['How are you, ', name, '?'].join();\n    }\n\n    \u002F\u002F bad\n    function sayHi(name) {\n      return `How are you, ${ name }?`;\n    }\n\n    \u002F\u002F good\n    function sayHi(name) {\n      return `How are you, ${name}?`;\n    }\n    ```\n\n  \u003Ca name=\"strings--eval\">\u003C\u002Fa>\u003Ca name=\"6.5\">\u003C\u002Fa>\n  - [6.4](#strings--eval) Never use `eval()` on a string; it opens too many vulnerabilities. eslint: [`no-eval`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-eval)\n\n  \u003Ca name=\"strings--escaping\">\u003C\u002Fa>\n  - [6.5](#strings--escaping) Do not unnecessarily escape characters in strings. eslint: [`no-useless-escape`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-useless-escape)\n\n    > Why? Backslashes harm readability, thus they should only be present when necessary.\n\n    ```javascript\n    \u002F\u002F bad\n    const foo = '\\'this\\' \\i\\s \\\"quoted\\\"';\n\n    \u002F\u002F good\n    const foo = '\\'this\\' is \"quoted\"';\n    const foo = `my name is '${name}'`;\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Functions\n\n  \u003Ca name=\"functions--declarations\">\u003C\u002Fa>\u003Ca name=\"7.1\">\u003C\u002Fa>\n  - [7.1](#functions--declarations) Use named function expressions instead of function declarations. eslint: [`func-style`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Ffunc-style), [`func-names`](https:\u002F\u002Feslint.org\u002Fdocs\u002Flatest\u002Frules\u002Ffunc-names)\n\n    > Why? Function declarations are hoisted, which means that it’s easy - too easy - to reference the function before it is defined in the file. This harms readability and maintainability. If you find that a function’s definition is large or complex enough that it is interfering with understanding the rest of the file, then perhaps it’s time to extract it to its own module! Don’t forget to explicitly name the expression, regardless of whether or not the name is inferred from the containing variable (which is often the case in modern browsers or when using compilers such as Babel). This eliminates any assumptions made about the Error’s call stack. ([Discussion](https:\u002F\u002Fgithub.com\u002Fairbnb\u002Fjavascript\u002Fissues\u002F794))\n\n    ```javascript\n    \u002F\u002F bad\n    function foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    const foo = function () {\n      \u002F\u002F ...\n    };\n\n    \u002F\u002F good\n    \u002F\u002F lexical name distinguished from the variable-referenced invocation(s)\n    const short = function longUniqueMoreDescriptiveLexicalFoo() {\n      \u002F\u002F ...\n    };\n    ```\n\n  \u003Ca name=\"functions--iife\">\u003C\u002Fa>\u003Ca name=\"7.2\">\u003C\u002Fa>\n  - [7.2](#functions--iife) Wrap immediately invoked function expressions in parentheses. eslint: [`wrap-iife`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fwrap-iife)\n\n    > Why? An immediately invoked function expression is a single unit - wrapping both it, and its invocation parens, in parens, cleanly expresses this. Note that in a world with modules everywhere, you almost never need an IIFE.\n\n    ```javascript\n    \u002F\u002F immediately-invoked function expression (IIFE)\n    (function () {\n      console.log('Welcome to the Internet. Please follow me.');\n    }());\n    ```\n\n  \u003Ca name=\"functions--in-blocks\">\u003C\u002Fa>\u003Ca name=\"7.3\">\u003C\u002Fa>\n  - [7.3](#functions--in-blocks) Never declare a function in a non-function block (`if`, `while`, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently, which is bad news bears. eslint: [`no-loop-func`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-loop-func)\n\n  \u003Ca name=\"functions--note-on-blocks\">\u003C\u002Fa>\u003Ca name=\"7.4\">\u003C\u002Fa>\n  - [7.4](#functions--note-on-blocks) **Note:** ECMA-262 defines a `block` as a list of statements. A function declaration is not a statement.\n\n    ```javascript\n    \u002F\u002F bad\n    if (currentUser) {\n      function test() {\n        console.log('Nope.');\n      }\n    }\n\n    \u002F\u002F good\n    let test;\n    if (currentUser) {\n      test = () => {\n        console.log('Yup.');\n      };\n    }\n    ```\n\n  \u003Ca name=\"functions--arguments-shadow\">\u003C\u002Fa>\u003Ca name=\"7.5\">\u003C\u002Fa>\n  - [7.5](#functions--arguments-shadow) Never name a parameter `arguments`. This will take precedence over the `arguments` object that is given to every function scope.\n\n    ```javascript\n    \u002F\u002F bad\n    function foo(name, options, arguments) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    function foo(name, options, args) {\n      \u002F\u002F ...\n    }\n    ```\n\n  \u003Ca name=\"es6-rest\">\u003C\u002Fa>\u003Ca name=\"7.6\">\u003C\u002Fa>\n  - [7.6](#es6-rest) Never use `arguments`, opt to use rest syntax `...` instead. eslint: [`prefer-rest-params`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-rest-params)\n\n    > Why? `...` is explicit about which arguments you want pulled. Plus, rest arguments are a real Array, and not merely Array-like like `arguments`.\n\n    ```javascript\n    \u002F\u002F bad\n    function concatenateAll() {\n      const args = Array.prototype.slice.call(arguments);\n      return args.join('');\n    }\n\n    \u002F\u002F good\n    function concatenateAll(...args) {\n      return args.join('');\n    }\n    ```\n\n  \u003Ca name=\"es6-default-parameters\">\u003C\u002Fa>\u003Ca name=\"7.7\">\u003C\u002Fa>\n  - [7.7](#es6-default-parameters) Use default parameter syntax rather than mutating function arguments.\n\n    ```javascript\n    \u002F\u002F really bad\n    function handleThings(opts) {\n      \u002F\u002F No! We shouldn’t mutate function arguments.\n      \u002F\u002F Double bad: if opts is falsy it'll be set to an object which may\n      \u002F\u002F be what you want but it can introduce subtle bugs.\n      opts = opts || {};\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F still bad\n    function handleThings(opts) {\n      if (opts === void 0) {\n        opts = {};\n      }\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    function handleThings(opts = {}) {\n      \u002F\u002F ...\n    }\n    ```\n\n  \u003Ca name=\"functions--default-side-effects\">\u003C\u002Fa>\u003Ca name=\"7.8\">\u003C\u002Fa>\n  - [7.8](#functions--default-side-effects) Avoid side effects with default parameters.\n\n    > Why? They are confusing to reason about.\n\n    ```javascript\n    let b = 1;\n    \u002F\u002F bad\n    function count(a = b++) {\n      console.log(a);\n    }\n    count();  \u002F\u002F 1\n    count();  \u002F\u002F 2\n    count(3); \u002F\u002F 3\n    count();  \u002F\u002F 3\n    ```\n\n  \u003Ca name=\"functions--defaults-last\">\u003C\u002Fa>\u003Ca name=\"7.9\">\u003C\u002Fa>\n  - [7.9](#functions--defaults-last) Always put default parameters last. eslint: [`default-param-last`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fdefault-param-last)\n\n    ```javascript\n    \u002F\u002F bad\n    function handleThings(opts = {}, name) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    function handleThings(name, opts = {}) {\n      \u002F\u002F ...\n    }\n    ```\n\n  \u003Ca name=\"functions--constructor\">\u003C\u002Fa>\u003Ca name=\"7.10\">\u003C\u002Fa>\n  - [7.10](#functions--constructor) Never use the Function constructor to create a new function. eslint: [`no-new-func`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-new-func)\n\n    > Why? Creating a function in this way evaluates a string similarly to `eval()`, which opens vulnerabilities.\n\n    ```javascript\n    \u002F\u002F bad\n    const add = new Function('a', 'b', 'return a + b');\n\n    \u002F\u002F still bad\n    const subtract = Function('a', 'b', 'return a - b');\n    ```\n\n  \u003Ca name=\"functions--signature-spacing\">\u003C\u002Fa>\u003Ca name=\"7.11\">\u003C\u002Fa>\n  - [7.11](#functions--signature-spacing) Spacing in a function signature. eslint: [`space-before-function-paren`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fspace-before-function-paren) [`space-before-blocks`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fspace-before-blocks)\n\n    > Why? Consistency is good, and you shouldn’t have to add or remove a space when adding or removing a name.\n\n    ```javascript\n    \u002F\u002F bad\n    const f = function(){};\n    const g = function (){};\n    const h = function() {};\n\n    \u002F\u002F good\n    const x = function () {};\n    const y = function a() {};\n    ```\n\n  \u003Ca name=\"functions--mutate-params\">\u003C\u002Fa>\u003Ca name=\"7.12\">\u003C\u002Fa>\n  - [7.12](#functions--mutate-params) Never mutate parameters. eslint: [`no-param-reassign`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-param-reassign)\n\n    > Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller.\n\n    ```javascript\n    \u002F\u002F bad\n    function f1(obj) {\n      obj.key = 1;\n    }\n\n    \u002F\u002F good\n    function f2(obj) {\n      const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;\n    }\n    ```\n\n  \u003Ca name=\"functions--reassign-params\">\u003C\u002Fa>\u003Ca name=\"7.13\">\u003C\u002Fa>\n  - [7.13](#functions--reassign-params) Never reassign parameters. eslint: [`no-param-reassign`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-param-reassign)\n\n    > Why? Reassigning parameters can lead to unexpected behavior, especially when accessing the `arguments` object. It can also cause optimization issues, especially in V8.\n\n    ```javascript\n    \u002F\u002F bad\n    function f1(a) {\n      a = 1;\n      \u002F\u002F ...\n    }\n\n    function f2(a) {\n      if (!a) { a = 1; }\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    function f3(a) {\n      const b = a || 1;\n      \u002F\u002F ...\n    }\n\n    function f4(a = 1) {\n      \u002F\u002F ...\n    }\n    ```\n\n  \u003Ca name=\"functions--spread-vs-apply\">\u003C\u002Fa>\u003Ca name=\"7.14\">\u003C\u002Fa>\n  - [7.14](#functions--spread-vs-apply) Prefer the use of the spread syntax `...` to call variadic functions. eslint: [`prefer-spread`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-spread)\n\n    > Why? It’s cleaner, you don’t need to supply a context, and you can not easily compose `new` with `apply`.\n\n    ```javascript\n    \u002F\u002F bad\n    const x = [1, 2, 3, 4, 5];\n    console.log.apply(console, x);\n\n    \u002F\u002F good\n    const x = [1, 2, 3, 4, 5];\n    console.log(...x);\n\n    \u002F\u002F bad\n    new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));\n\n    \u002F\u002F good\n    new Date(...[2016, 8, 5]);\n    ```\n\n  \u003Ca name=\"functions--signature-invocation-indentation\">\u003C\u002Fa>\n  - [7.15](#functions--signature-invocation-indentation) Functions with multiline signatures, or invocations, should be indented just like every other multiline list in this guide: with each item on a line by itself, with a trailing comma on the last item. eslint: [`function-paren-newline`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Ffunction-paren-newline)\n\n    ```javascript\n    \u002F\u002F bad\n    function foo(bar,\n                 baz,\n                 quux) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    function foo(\n      bar,\n      baz,\n      quux,\n    ) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    console.log(foo,\n      bar,\n      baz);\n\n    \u002F\u002F good\n    console.log(\n      foo,\n      bar,\n      baz,\n    );\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Arrow Functions\n\n  \u003Ca name=\"arrows--use-them\">\u003C\u002Fa>\u003Ca name=\"8.1\">\u003C\u002Fa>\n  - [8.1](#arrows--use-them) When you must use an anonymous function (as when passing an inline callback), use arrow function notation. eslint: [`prefer-arrow-callback`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-arrow-callback), [`arrow-spacing`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Farrow-spacing)\n\n    > 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.\n\n    > Why not? If you have a fairly complicated function, you might move that logic out into its own named function expression.\n\n    ```javascript\n    \u002F\u002F bad\n    [1, 2, 3].map(function (x) {\n      const y = x + 1;\n      return x * y;\n    });\n\n    \u002F\u002F good\n    [1, 2, 3].map((x) => {\n      const y = x + 1;\n      return x * y;\n    });\n    ```\n\n  \u003Ca name=\"arrows--implicit-return\">\u003C\u002Fa>\u003Ca name=\"8.2\">\u003C\u002Fa>\n  - [8.2](#arrows--implicit-return) If the function body consists of a single statement returning an [expression](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FExpressions_and_Operators#Expressions) without side effects, omit the braces and use the implicit return. Otherwise, keep the braces and use a `return` statement. eslint: [`arrow-parens`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Farrow-parens), [`arrow-body-style`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Farrow-body-style)\n\n    > Why? Syntactic sugar. It reads well when multiple functions are chained together.\n\n    ```javascript\n    \u002F\u002F bad\n    [1, 2, 3].map((number) => {\n      const nextNumber = number + 1;\n      `A string containing the ${nextNumber}.`;\n    });\n\n    \u002F\u002F good\n    [1, 2, 3].map((number) => `A string containing the ${number + 1}.`);\n\n    \u002F\u002F good\n    [1, 2, 3].map((number) => {\n      const nextNumber = number + 1;\n      return `A string containing the ${nextNumber}.`;\n    });\n\n    \u002F\u002F good\n    [1, 2, 3].map((number, index) => ({\n      [index]: number,\n    }));\n\n    \u002F\u002F No implicit return with side effects\n    function foo(callback) {\n      const val = callback();\n      if (val === true) {\n        \u002F\u002F Do something if callback returns true\n      }\n    }\n\n    let bool = false;\n\n    \u002F\u002F bad\n    foo(() => bool = true);\n\n    \u002F\u002F good\n    foo(() => {\n      bool = true;\n    });\n    ```\n\n  \u003Ca name=\"arrows--paren-wrap\">\u003C\u002Fa>\u003Ca name=\"8.3\">\u003C\u002Fa>\n  - [8.3](#arrows--paren-wrap) In case the expression spans over multiple lines, wrap it in parentheses for better readability.\n\n    > Why? It shows clearly where the function starts and ends.\n\n    ```javascript\n    \u002F\u002F bad\n    ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call(\n        httpMagicObjectWithAVeryLongName,\n        httpMethod,\n      )\n    );\n\n    \u002F\u002F good\n    ['get', 'post', 'put'].map((httpMethod) => (\n      Object.prototype.hasOwnProperty.call(\n        httpMagicObjectWithAVeryLongName,\n        httpMethod,\n      )\n    ));\n    ```\n\n  \u003Ca name=\"arrows--one-arg-parens\">\u003C\u002Fa>\u003Ca name=\"8.4\">\u003C\u002Fa>\n  - [8.4](#arrows--one-arg-parens) Always include parentheses around arguments for clarity and consistency. eslint: [`arrow-parens`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Farrow-parens)\n\n    > Why? Minimizes diff churn when adding or removing arguments.\n\n    ```javascript\n    \u002F\u002F bad\n    [1, 2, 3].map(x => x * x);\n\n    \u002F\u002F good\n    [1, 2, 3].map((x) => x * x);\n\n    \u002F\u002F bad\n    [1, 2, 3].map(number => (\n      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`\n    ));\n\n    \u002F\u002F good\n    [1, 2, 3].map((number) => (\n      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`\n    ));\n\n    \u002F\u002F bad\n    [1, 2, 3].map(x => {\n      const y = x + 1;\n      return x * y;\n    });\n\n    \u002F\u002F good\n    [1, 2, 3].map((x) => {\n      const y = x + 1;\n      return x * y;\n    });\n    ```\n\n  \u003Ca name=\"arrows--confusing\">\u003C\u002Fa>\u003Ca name=\"8.5\">\u003C\u002Fa>\n  - [8.5](#arrows--confusing) Avoid confusing arrow function syntax (`=>`) with comparison operators (`\u003C=`, `>=`). eslint: [`no-confusing-arrow`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-confusing-arrow)\n\n    ```javascript\n    \u002F\u002F bad\n    const itemHeight = (item) => item.height \u003C= 256 ? item.largeSize : item.smallSize;\n\n    \u002F\u002F bad\n    const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;\n\n    \u002F\u002F good\n    const itemHeight = (item) => (item.height \u003C= 256 ? item.largeSize : item.smallSize);\n\n    \u002F\u002F good\n    const itemHeight = (item) => {\n      const { height, largeSize, smallSize } = item;\n      return height \u003C= 256 ? largeSize : smallSize;\n    };\n    ```\n\n  \u003Ca name=\"whitespace--implicit-arrow-linebreak\">\u003C\u002Fa>\n  - [8.6](#whitespace--implicit-arrow-linebreak) Enforce the location of arrow function bodies with implicit returns. eslint: [`implicit-arrow-linebreak`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fimplicit-arrow-linebreak)\n\n    ```javascript\n    \u002F\u002F bad\n    (foo) =>\n      bar;\n\n    (foo) =>\n      (bar);\n\n    \u002F\u002F good\n    (foo) => bar;\n    (foo) => (bar);\n    (foo) => (\n       bar\n    )\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Classes & Constructors\n\n  \u003Ca name=\"constructors--use-class\">\u003C\u002Fa>\u003Ca name=\"9.1\">\u003C\u002Fa>\n  - [9.1](#constructors--use-class) Always use `class`. Avoid manipulating `prototype` directly.\n\n    > Why? `class` syntax is more concise and easier to reason about.\n\n    ```javascript\n    \u002F\u002F bad\n    function Queue(contents = []) {\n      this.queue = [...contents];\n    }\n    Queue.prototype.pop = function () {\n      const value = this.queue[0];\n      this.queue.splice(0, 1);\n      return value;\n    };\n\n    \u002F\u002F good\n    class Queue {\n      constructor(contents = []) {\n        this.queue = [...contents];\n      }\n      pop() {\n        const value = this.queue[0];\n        this.queue.splice(0, 1);\n        return value;\n      }\n    }\n    ```\n\n  \u003Ca name=\"constructors--extends\">\u003C\u002Fa>\u003Ca name=\"9.2\">\u003C\u002Fa>\n  - [9.2](#constructors--extends) Use `extends` for inheritance.\n\n    > Why? It is a built-in way to inherit prototype functionality without breaking `instanceof`.\n\n    ```javascript\n    \u002F\u002F bad\n    const inherits = require('inherits');\n    function PeekableQueue(contents) {\n      Queue.apply(this, contents);\n    }\n    inherits(PeekableQueue, Queue);\n    PeekableQueue.prototype.peek = function () {\n      return this.queue[0];\n    };\n\n    \u002F\u002F good\n    class PeekableQueue extends Queue {\n      peek() {\n        return this.queue[0];\n      }\n    }\n    ```\n\n  \u003Ca name=\"constructors--chaining\">\u003C\u002Fa>\u003Ca name=\"9.3\">\u003C\u002Fa>\n  - [9.3](#constructors--chaining) Methods can return `this` to help with method chaining.\n\n    ```javascript\n    \u002F\u002F bad\n    Jedi.prototype.jump = function () {\n      this.jumping = true;\n      return true;\n    };\n\n    Jedi.prototype.setHeight = function (height) {\n      this.height = height;\n    };\n\n    const luke = new Jedi();\n    luke.jump(); \u002F\u002F => true\n    luke.setHeight(20); \u002F\u002F => undefined\n\n    \u002F\u002F good\n    class Jedi {\n      jump() {\n        this.jumping = true;\n        return this;\n      }\n\n      setHeight(height) {\n        this.height = height;\n        return this;\n      }\n    }\n\n    const luke = new Jedi();\n\n    luke.jump()\n      .setHeight(20);\n    ```\n\n  \u003Ca name=\"constructors--tostring\">\u003C\u002Fa>\u003Ca name=\"9.4\">\u003C\u002Fa>\n  - [9.4](#constructors--tostring) It’s okay to write a custom `toString()` method, just make sure it works successfully and causes no side effects.\n\n    ```javascript\n    class Jedi {\n      constructor(options = {}) {\n        this.name = options.name || 'no name';\n      }\n\n      getName() {\n        return this.name;\n      }\n\n      toString() {\n        return `Jedi - ${this.getName()}`;\n      }\n    }\n    ```\n\n  \u003Ca name=\"constructors--no-useless\">\u003C\u002Fa>\u003Ca name=\"9.5\">\u003C\u002Fa>\n  - [9.5](#constructors--no-useless) Classes have a default constructor if one is not specified. An empty constructor function or one that just delegates to a parent class is unnecessary. eslint: [`no-useless-constructor`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-useless-constructor)\n\n    ```javascript\n    \u002F\u002F bad\n    class Jedi {\n      constructor() {}\n\n      getName() {\n        return this.name;\n      }\n    }\n\n    \u002F\u002F bad\n    class Rey extends Jedi {\n      constructor(...args) {\n        super(...args);\n      }\n    }\n\n    \u002F\u002F good\n    class Rey extends Jedi {\n      constructor(...args) {\n        super(...args);\n        this.name = 'Rey';\n      }\n    }\n    ```\n\n  \u003Ca name=\"classes--no-duplicate-members\">\u003C\u002Fa>\n  - [9.6](#classes--no-duplicate-members) Avoid duplicate class members. eslint: [`no-dupe-class-members`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-dupe-class-members)\n\n    > Why? Duplicate class member declarations will silently prefer the last one - having duplicates is almost certainly a bug.\n\n    ```javascript\n    \u002F\u002F bad\n    class Foo {\n      bar() { return 1; }\n      bar() { return 2; }\n    }\n\n    \u002F\u002F good\n    class Foo {\n      bar() { return 1; }\n    }\n\n    \u002F\u002F good\n    class Foo {\n      bar() { return 2; }\n    }\n    ```\n\n  \u003Ca name=\"classes--methods-use-this\">\u003C\u002Fa>\n  - [9.7](#classes--methods-use-this) Class methods should use `this` or be made into a static method unless an external library or framework requires using specific non-static methods. Being an instance method should indicate that it behaves differently based on properties of the receiver. eslint: [`class-methods-use-this`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fclass-methods-use-this)\n\n    ```javascript\n    \u002F\u002F bad\n    class Foo {\n      bar() {\n        console.log('bar');\n      }\n    }\n\n    \u002F\u002F good - this is used\n    class Foo {\n      bar() {\n        console.log(this.bar);\n      }\n    }\n\n    \u002F\u002F good - constructor is exempt\n    class Foo {\n      constructor() {\n        \u002F\u002F ...\n      }\n    }\n\n    \u002F\u002F good - static methods aren't expected to use this\n    class Foo {\n      static bar() {\n        console.log('bar');\n      }\n    }\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Modules\n\n  \u003Ca name=\"modules--use-them\">\u003C\u002Fa>\u003Ca name=\"10.1\">\u003C\u002Fa>\n  - [10.1](#modules--use-them) Always use modules (`import`\u002F`export`) over a non-standard module system. You can always transpile to your preferred module system.\n\n    > Why? Modules are the future, let’s start using the future now.\n\n    ```javascript\n    \u002F\u002F bad\n    const AirbnbStyleGuide = require('.\u002FAirbnbStyleGuide');\n    module.exports = AirbnbStyleGuide.es6;\n\n    \u002F\u002F ok\n    import AirbnbStyleGuide from '.\u002FAirbnbStyleGuide';\n    export default AirbnbStyleGuide.es6;\n\n    \u002F\u002F best\n    import { es6 } from '.\u002FAirbnbStyleGuide';\n    export default es6;\n    ```\n\n  \u003Ca name=\"modules--no-wildcard\">\u003C\u002Fa>\u003Ca name=\"10.2\">\u003C\u002Fa>\n  - [10.2](#modules--no-wildcard) Do not use wildcard imports.\n\n    > Why? This makes sure you have a single default export.\n\n    ```javascript\n    \u002F\u002F bad\n    import * as AirbnbStyleGuide from '.\u002FAirbnbStyleGuide';\n\n    \u002F\u002F good\n    import AirbnbStyleGuide from '.\u002FAirbnbStyleGuide';\n    ```\n\n  \u003Ca name=\"modules--no-export-from-import\">\u003C\u002Fa>\u003Ca name=\"10.3\">\u003C\u002Fa>\n  - [10.3](#modules--no-export-from-import) And do not export directly from an import.\n\n    > Why? Although the one-liner is concise, having one clear way to import and one clear way to export makes things consistent.\n\n    ```javascript\n    \u002F\u002F bad\n    \u002F\u002F filename es6.js\n    export { es6 as default } from '.\u002FAirbnbStyleGuide';\n\n    \u002F\u002F good\n    \u002F\u002F filename es6.js\n    import { es6 } from '.\u002FAirbnbStyleGuide';\n    export default es6;\n    ```\n\n  \u003Ca name=\"modules--no-duplicate-imports\">\u003C\u002Fa>\n  - [10.4](#modules--no-duplicate-imports) Only import from a path in one place.\n eslint: [`no-duplicate-imports`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-duplicate-imports)\n    > Why? Having multiple lines that import from the same path can make code harder to maintain.\n\n    ```javascript\n    \u002F\u002F bad\n    import foo from 'foo';\n    \u002F\u002F … some other imports … \u002F\u002F\n    import { named1, named2 } from 'foo';\n\n    \u002F\u002F good\n    import foo, { named1, named2 } from 'foo';\n\n    \u002F\u002F good\n    import foo, {\n      named1,\n      named2,\n    } from 'foo';\n    ```\n\n  \u003Ca name=\"modules--no-mutable-exports\">\u003C\u002Fa>\n  - [10.5](#modules--no-mutable-exports) Do not export mutable bindings.\n eslint: [`import\u002Fno-mutable-exports`](https:\u002F\u002Fgithub.com\u002Fimport-js\u002Feslint-plugin-import\u002Fblob\u002Fmaster\u002Fdocs\u002Frules\u002Fno-mutable-exports.md)\n    > Why? Mutation should be avoided in general, but in particular when exporting mutable bindings. While this technique may be needed for some special cases, in general, only constant references should be exported.\n\n    ```javascript\n    \u002F\u002F bad\n    let foo = 3;\n    export { foo };\n\n    \u002F\u002F good\n    const foo = 3;\n    export { foo };\n    ```\n\n  \u003Ca name=\"modules--prefer-default-export\">\u003C\u002Fa>\n  - [10.6](#modules--prefer-default-export) In modules with a single export, prefer default export over named export.\n eslint: [`import\u002Fprefer-default-export`](https:\u002F\u002Fgithub.com\u002Fimport-js\u002Feslint-plugin-import\u002Fblob\u002Fmaster\u002Fdocs\u002Frules\u002Fprefer-default-export.md)\n    > Why? To encourage more files that only ever export one thing, which is better for readability and maintainability.\n\n    ```javascript\n    \u002F\u002F bad\n    export function foo() {}\n\n    \u002F\u002F good\n    export default function foo() {}\n    ```\n\n  \u003Ca name=\"modules--imports-first\">\u003C\u002Fa>\n  - [10.7](#modules--imports-first) Put all `import`s above non-import statements.\n eslint: [`import\u002Ffirst`](https:\u002F\u002Fgithub.com\u002Fimport-js\u002Feslint-plugin-import\u002Fblob\u002Fmaster\u002Fdocs\u002Frules\u002Ffirst.md)\n    > Why? Since `import`s are hoisted, keeping them all at the top prevents surprising behavior.\n\n    ```javascript\n    \u002F\u002F bad\n    import foo from 'foo';\n    foo.init();\n\n    import bar from 'bar';\n\n    \u002F\u002F good\n    import foo from 'foo';\n    import bar from 'bar';\n\n    foo.init();\n    ```\n\n  \u003Ca name=\"modules--multiline-imports-over-newlines\">\u003C\u002Fa>\n  - [10.8](#modules--multiline-imports-over-newlines) Multiline imports should be indented just like multiline array and object literals.\n eslint: [`object-curly-newline`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fobject-curly-newline)\n\n    > Why? The curly braces follow the same indentation rules as every other curly brace block in the style guide, as do the trailing commas.\n\n    ```javascript\n    \u002F\u002F bad\n    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';\n\n    \u002F\u002F good\n    import {\n      longNameA,\n      longNameB,\n      longNameC,\n      longNameD,\n      longNameE,\n    } from 'path';\n    ```\n\n  \u003Ca name=\"modules--no-webpack-loader-syntax\">\u003C\u002Fa>\n  - [10.9](#modules--no-webpack-loader-syntax) Disallow Webpack loader syntax in module import statements.\n eslint: [`import\u002Fno-webpack-loader-syntax`](https:\u002F\u002Fgithub.com\u002Fimport-js\u002Feslint-plugin-import\u002Fblob\u002Fmaster\u002Fdocs\u002Frules\u002Fno-webpack-loader-syntax.md)\n    > Why? Since using Webpack syntax in the imports couples the code to a module bundler. Prefer using the loader syntax in `webpack.config.js`.\n\n    ```javascript\n    \u002F\u002F bad\n    import fooSass from 'css!sass!foo.scss';\n    import barCss from 'style!css!bar.css';\n\n    \u002F\u002F good\n    import fooSass from 'foo.scss';\n    import barCss from 'bar.css';\n    ```\n\n  \u003Ca name=\"modules--import-extensions\">\u003C\u002Fa>\n  - [10.10](#modules--import-extensions) Do not include JavaScript filename extensions\n eslint: [`import\u002Fextensions`](https:\u002F\u002Fgithub.com\u002Fimport-js\u002Feslint-plugin-import\u002Fblob\u002Fmaster\u002Fdocs\u002Frules\u002Fextensions.md)\n    > Why? Including extensions inhibits refactoring, and inappropriately hardcodes implementation details of the module you're importing in every consumer.\n\n    ```javascript\n    \u002F\u002F bad\n    import foo from '.\u002Ffoo.js';\n    import bar from '.\u002Fbar.jsx';\n    import baz from '.\u002Fbaz\u002Findex.jsx';\n\n    \u002F\u002F good\n    import foo from '.\u002Ffoo';\n    import bar from '.\u002Fbar';\n    import baz from '.\u002Fbaz';\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Iterators and Generators\n\n  \u003Ca name=\"iterators--nope\">\u003C\u002Fa>\u003Ca name=\"11.1\">\u003C\u002Fa>\n  - [11.1](#iterators--nope) Don’t use iterators. Prefer JavaScript’s higher-order functions instead of loops like `for-in` or `for-of`. eslint: [`no-iterator`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-iterator) [`no-restricted-syntax`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-restricted-syntax)\n\n    > Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.\n\n    > Use `map()` \u002F `every()` \u002F `filter()` \u002F `find()` \u002F `findIndex()` \u002F `reduce()` \u002F `some()` \u002F ... to iterate over arrays, and `Object.keys()` \u002F `Object.values()` \u002F `Object.entries()` to produce arrays so you can iterate over objects.\n\n    ```javascript\n    const numbers = [1, 2, 3, 4, 5];\n\n    \u002F\u002F bad\n    let sum = 0;\n    for (let num of numbers) {\n      sum += num;\n    }\n    sum === 15;\n\n    \u002F\u002F good\n    let sum = 0;\n    numbers.forEach((num) => {\n      sum += num;\n    });\n    sum === 15;\n\n    \u002F\u002F best (use the functional force)\n    const sum = numbers.reduce((total, num) => total + num, 0);\n    sum === 15;\n\n    \u002F\u002F bad\n    const increasedByOne = [];\n    for (let i = 0; i \u003C numbers.length; i++) {\n      increasedByOne.push(numbers[i] + 1);\n    }\n\n    \u002F\u002F good\n    const increasedByOne = [];\n    numbers.forEach((num) => {\n      increasedByOne.push(num + 1);\n    });\n\n    \u002F\u002F best (keeping it functional)\n    const increasedByOne = numbers.map((num) => num + 1);\n    ```\n\n  \u003Ca name=\"generators--nope\">\u003C\u002Fa>\u003Ca name=\"11.2\">\u003C\u002Fa>\n  - [11.2](#generators--nope) Don’t use generators for now.\n\n    > Why? They don’t transpile well to ES5.\n\n  \u003Ca name=\"generators--spacing\">\u003C\u002Fa>\n  - [11.3](#generators--spacing) If you must use generators, or if you disregard [our advice](#generators--nope), make sure their function signature is spaced properly. eslint: [`generator-star-spacing`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fgenerator-star-spacing)\n\n    > Why? `function` and `*` are part of the same conceptual keyword - `*` is not a modifier for `function`, `function*` is a unique construct, different from `function`.\n\n    ```javascript\n    \u002F\u002F bad\n    function * foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    const bar = function * () {\n      \u002F\u002F ...\n    };\n\n    \u002F\u002F bad\n    const baz = function *() {\n      \u002F\u002F ...\n    };\n\n    \u002F\u002F bad\n    const quux = function*() {\n      \u002F\u002F ...\n    };\n\n    \u002F\u002F bad\n    function*foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    function *foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F very bad\n    function\n    *\n    foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F very bad\n    const wat = function\n    *\n    () {\n      \u002F\u002F ...\n    };\n\n    \u002F\u002F good\n    function* foo() {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    const foo = function* () {\n      \u002F\u002F ...\n    };\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Properties\n\n  \u003Ca name=\"properties--dot\">\u003C\u002Fa>\u003Ca name=\"12.1\">\u003C\u002Fa>\n  - [12.1](#properties--dot) Use dot notation when accessing properties. eslint: [`dot-notation`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fdot-notation)\n\n    ```javascript\n    const luke = {\n      jedi: true,\n      age: 28,\n    };\n\n    \u002F\u002F bad\n    const isJedi = luke['jedi'];\n\n    \u002F\u002F good\n    const isJedi = luke.jedi;\n    ```\n\n  \u003Ca name=\"properties--bracket\">\u003C\u002Fa>\u003Ca name=\"12.2\">\u003C\u002Fa>\n  - [12.2](#properties--bracket) Use bracket notation `[]` when accessing properties with a variable.\n\n    ```javascript\n    const luke = {\n      jedi: true,\n      age: 28,\n    };\n\n    function getProp(prop) {\n      return luke[prop];\n    }\n\n    const isJedi = getProp('jedi');\n    ```\n\n  \u003Ca name=\"es2016-properties--exponentiation-operator\">\u003C\u002Fa>\n  - [12.3](#es2016-properties--exponentiation-operator) Use exponentiation operator `**` when calculating exponentiations. eslint: [`prefer-exponentiation-operator`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-exponentiation-operator).\n\n    ```javascript\n    \u002F\u002F bad\n    const binary = Math.pow(2, 10);\n\n    \u002F\u002F good\n    const binary = 2 ** 10;\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Variables\n\n  \u003Ca name=\"variables--const\">\u003C\u002Fa>\u003Ca name=\"13.1\">\u003C\u002Fa>\n  - [13.1](#variables--const) Always use `const` or `let` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that. eslint: [`no-undef`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-undef) [`prefer-const`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fprefer-const)\n\n    ```javascript\n    \u002F\u002F bad\n    superPower = new SuperPower();\n\n    \u002F\u002F good\n    const superPower = new SuperPower();\n    ```\n\n  \u003Ca name=\"variables--one-const\">\u003C\u002Fa>\u003Ca name=\"13.2\">\u003C\u002Fa>\n  - [13.2](#variables--one-const) Use one `const` or `let` declaration per variable or assignment. eslint: [`one-var`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fone-var)\n\n    > 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. You can also step through each declaration with the debugger, instead of jumping through all of them at once.\n\n    ```javascript\n    \u002F\u002F bad\n    const items = getItems(),\n        goSportsTeam = true,\n        dragonball = 'z';\n\n    \u002F\u002F bad\n    \u002F\u002F (compare to above, and try to spot the mistake)\n    const items = getItems(),\n        goSportsTeam = true;\n        dragonball = 'z';\n\n    \u002F\u002F good\n    const items = getItems();\n    const goSportsTeam = true;\n    const dragonball = 'z';\n    ```\n\n  \u003Ca name=\"variables--const-let-group\">\u003C\u002Fa>\u003Ca name=\"13.3\">\u003C\u002Fa>\n  - [13.3](#variables--const-let-group) Group all your `const`s and then group all your `let`s.\n\n    > Why? This is helpful when later on you might need to assign a variable depending on one of the previously assigned variables.\n\n    ```javascript\n    \u002F\u002F bad\n    let i, len, dragonball,\n        items = getItems(),\n        goSportsTeam = true;\n\n    \u002F\u002F bad\n    let i;\n    const items = getItems();\n    let dragonball;\n    const goSportsTeam = true;\n    let len;\n\n    \u002F\u002F good\n    const goSportsTeam = true;\n    const items = getItems();\n    let dragonball;\n    let i;\n    let length;\n    ```\n\n  \u003Ca name=\"variables--define-where-used\">\u003C\u002Fa>\u003Ca name=\"13.4\">\u003C\u002Fa>\n  - [13.4](#variables--define-where-used) Assign variables where you need them, but place them in a reasonable place.\n\n    > Why? `let` and `const` are block scoped and not function scoped.\n\n    ```javascript\n    \u002F\u002F bad - unnecessary function call\n    function checkName(hasName) {\n      const name = getName();\n\n      if (hasName === 'test') {\n        return false;\n      }\n\n      if (name === 'test') {\n        this.setName('');\n        return false;\n      }\n\n      return name;\n    }\n\n    \u002F\u002F good\n    function checkName(hasName) {\n      if (hasName === 'test') {\n        return false;\n      }\n\n      const name = getName();\n\n      if (name === 'test') {\n        this.setName('');\n        return false;\n      }\n\n      return name;\n    }\n    ```\n\n  \u003Ca name=\"variables--no-chain-assignment\">\u003C\u002Fa>\u003Ca name=\"13.5\">\u003C\u002Fa>\n  - [13.5](#variables--no-chain-assignment) Don’t chain variable assignments. eslint: [`no-multi-assign`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-multi-assign)\n\n    > Why? Chaining variable assignments creates implicit global variables.\n\n    ```javascript\n    \u002F\u002F bad\n    (function example() {\n      \u002F\u002F JavaScript interprets this as\n      \u002F\u002F let a = ( b = ( c = 1 ) );\n      \u002F\u002F The let keyword only applies to variable a; variables b and c become\n      \u002F\u002F global variables.\n      let a = b = c = 1;\n    }());\n\n    console.log(a); \u002F\u002F throws ReferenceError\n    console.log(b); \u002F\u002F 1\n    console.log(c); \u002F\u002F 1\n\n    \u002F\u002F good\n    (function example() {\n      let a = 1;\n      let b = a;\n      let c = a;\n    }());\n\n    console.log(a); \u002F\u002F throws ReferenceError\n    console.log(b); \u002F\u002F throws ReferenceError\n    console.log(c); \u002F\u002F throws ReferenceError\n\n    \u002F\u002F the same applies for `const`\n    ```\n\n  \u003Ca name=\"variables--unary-increment-decrement\">\u003C\u002Fa>\u003Ca name=\"13.6\">\u003C\u002Fa>\n  - [13.6](#variables--unary-increment-decrement) Avoid using unary increments and decrements (`++`, `--`). eslint [`no-plusplus`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-plusplus)\n\n    > Why? Per the eslint documentation, unary increment and decrement statements are subject to automatic semicolon insertion and can cause silent errors with incrementing or decrementing values within an application. It is also more expressive to mutate your values with statements like `num += 1` instead of `num++` or `num ++`. Disallowing unary increment and decrement statements also prevents you from pre-incrementing\u002Fpre-decrementing values unintentionally which can also cause unexpected behavior in your programs.\n\n    ```javascript\n    \u002F\u002F bad\n\n    const array = [1, 2, 3];\n    let num = 1;\n    num++;\n    --num;\n\n    let sum = 0;\n    let truthyCount = 0;\n    for (let i = 0; i \u003C array.length; i++) {\n      let value = array[i];\n      sum += value;\n      if (value) {\n        truthyCount++;\n      }\n    }\n\n    \u002F\u002F good\n\n    const array = [1, 2, 3];\n    let num = 1;\n    num += 1;\n    num -= 1;\n\n    const sum = array.reduce((a, b) => a + b, 0);\n    const truthyCount = array.filter(Boolean).length;\n    ```\n\n\u003Ca name=\"variables--linebreak\">\u003C\u002Fa>\n  - [13.7](#variables--linebreak) Avoid linebreaks before or after `=` in an assignment. If your assignment violates [`max-len`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fmax-len), surround the value in parens. eslint [`operator-linebreak`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Foperator-linebreak).\n\n    > Why? Linebreaks surrounding `=` can obfuscate the value of an assignment.\n\n    ```javascript\n    \u002F\u002F bad\n    const foo =\n      superLongLongLongLongLongLongLongLongFunctionName();\n\n    \u002F\u002F bad\n    const foo\n      = 'superLongLongLongLongLongLongLongLongString';\n\n    \u002F\u002F good\n    const foo = (\n      superLongLongLongLongLongLongLongLongFunctionName()\n    );\n\n    \u002F\u002F good\n    const foo = 'superLongLongLongLongLongLongLongLongString';\n    ```\n\n\u003Ca name=\"variables--no-unused-vars\">\u003C\u002Fa>\n  - [13.8](#variables--no-unused-vars) Disallow unused variables. eslint: [`no-unused-vars`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-unused-vars)\n\n    > Why? Variables that are declared and not used anywhere in the code are most likely an error due to incomplete refactoring. Such variables take up space in the code and can lead to confusion by readers.\n\n    ```javascript\n    \u002F\u002F bad\n\n    const some_unused_var = 42;\n\n    \u002F\u002F Write-only variables are not considered as used.\n    let y = 10;\n    y = 5;\n\n    \u002F\u002F A read for a modification of itself is not considered as used.\n    let z = 0;\n    z = z + 1;\n\n    \u002F\u002F Unused function arguments.\n    function getX(x, y) {\n        return x;\n    }\n\n    \u002F\u002F good\n\n    function getXPlusY(x, y) {\n      return x + y;\n    }\n\n    const x = 1;\n    const y = a + 2;\n\n    alert(getXPlusY(x, y));\n\n    \u002F\u002F 'type' is ignored even if unused because it has a rest property sibling.\n    \u002F\u002F This is a form of extracting an object that omits the specified keys.\n    const { type, ...coords } = data;\n    \u002F\u002F 'coords' is now the 'data' object without its 'type' property.\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Hoisting\n\n  \u003Ca name=\"hoisting--about\">\u003C\u002Fa>\u003Ca name=\"14.1\">\u003C\u002Fa>\n  - [14.1](#hoisting--about) `var` declarations get hoisted to the top of their closest enclosing function scope, their assignment does not. `const` and `let` declarations are blessed with a new concept called [Temporal Dead Zones (TDZ)](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FStatements\u002Flet#temporal_dead_zone_tdz). It’s important to know why [typeof is no longer safe](https:\u002F\u002Fweb.archive.org\u002Fweb\u002F20200121061528\u002Fhttp:\u002F\u002Fes-discourse.com\u002Ft\u002Fwhy-typeof-is-no-longer-safe\u002F15).\n\n    ```javascript\n    \u002F\u002F we know this wouldn’t work (assuming there\n    \u002F\u002F is no notDefined global variable)\n    function example() {\n      console.log(notDefined); \u002F\u002F => throws a ReferenceError\n    }\n\n    \u002F\u002F creating a variable declaration after you\n    \u002F\u002F reference the variable will work due to\n    \u002F\u002F variable hoisting. Note: the assignment\n    \u002F\u002F value of `true` is not hoisted.\n    function example() {\n      console.log(declaredButNotAssigned); \u002F\u002F => undefined\n      var declaredButNotAssigned = true;\n    }\n\n    \u002F\u002F the interpreter is hoisting the variable\n    \u002F\u002F declaration to the top of the scope,\n    \u002F\u002F which means our example could be rewritten as:\n    function example() {\n      let declaredButNotAssigned;\n      console.log(declaredButNotAssigned); \u002F\u002F => undefined\n      declaredButNotAssigned = true;\n    }\n\n    \u002F\u002F using const and let\n    function example() {\n      console.log(declaredButNotAssigned); \u002F\u002F => throws a ReferenceError\n      console.log(typeof declaredButNotAssigned); \u002F\u002F => throws a ReferenceError\n      const declaredButNotAssigned = true;\n    }\n    ```\n\n  \u003Ca name=\"hoisting--anon-expressions\">\u003C\u002Fa>\u003Ca name=\"14.2\">\u003C\u002Fa>\n  - [14.2](#hoisting--anon-expressions) Anonymous function expressions hoist their variable name, but not the function assignment.\n\n    ```javascript\n    function example() {\n      console.log(anonymous); \u002F\u002F => undefined\n\n      anonymous(); \u002F\u002F => TypeError anonymous is not a function\n\n      var anonymous = function () {\n        console.log('anonymous function expression');\n      };\n    }\n    ```\n\n  \u003Ca name=\"hoisting--named-expresions\">\u003C\u002Fa>\u003Ca name=\"hoisting--named-expressions\">\u003C\u002Fa>\u003Ca name=\"14.3\">\u003C\u002Fa>\n  - [14.3](#hoisting--named-expressions) Named function expressions hoist the variable name, not the function name or the function body.\n\n    ```javascript\n    function example() {\n      console.log(named); \u002F\u002F => undefined\n\n      named(); \u002F\u002F => TypeError named is not a function\n\n      superPower(); \u002F\u002F => ReferenceError superPower is not defined\n\n      var named = function superPower() {\n        console.log('Flying');\n      };\n    }\n\n    \u002F\u002F the same is true when the function name\n    \u002F\u002F is the same as the variable name.\n    function example() {\n      console.log(named); \u002F\u002F => undefined\n\n      named(); \u002F\u002F => TypeError named is not a function\n\n      var named = function named() {\n        console.log('named');\n      };\n    }\n    ```\n\n  \u003Ca name=\"hoisting--declarations\">\u003C\u002Fa>\u003Ca name=\"14.4\">\u003C\u002Fa>\n  - [14.4](#hoisting--declarations) Function declarations hoist their name and the function body.\n\n    ```javascript\n    function example() {\n      superPower(); \u002F\u002F => Flying\n\n      function superPower() {\n        console.log('Flying');\n      }\n    }\n    ```\n\n  \u003Ca name=\"no-use-before-define\">\u003C\u002Fa>\n  - [14.5](#no-use-before-define) Variables, classes, and functions should be defined before they can be used. eslint: [`no-use-before-define`](https:\u002F\u002Feslint.org\u002Fdocs\u002Flatest\u002Frules\u002Fno-use-before-define)\n\n    > Why? When variables, classes, or functions are declared after being used, it can harm readability since a reader won't know what a thing that's referenced is. It's much clearer for a reader to first encounter the source of a thing (whether imported from another module, or defined in the file) before encountering a use of the thing.\n\n    ```javascript\n    \u002F\u002F bad\n\n    \u002F\u002F Variable a is being used before it is being defined.\n    console.log(a); \u002F\u002F this will be undefined, since while the declaration is hoisted, the initialization is not\n    var a = 10;\n\n    \u002F\u002F Function fun is being called before being defined.\n    fun();\n    function fun() {}\n\n    \u002F\u002F Class A is being used before being defined.\n    new A(); \u002F\u002F ReferenceError: Cannot access 'A' before initialization\n    class A {\n    }\n\n    \u002F\u002F `let` and `const` are hoisted, but they don't have a default initialization.\n    \u002F\u002F The variables 'a' and 'b' are in a Temporal Dead Zone where JavaScript\n    \u002F\u002F knows they exist (declaration is hoisted) but they are not accessible\n    \u002F\u002F (as they are not yet initialized).\n\n    console.log(a); \u002F\u002F ReferenceError: Cannot access 'a' before initialization\n    console.log(b); \u002F\u002F ReferenceError: Cannot access 'b' before initialization\n    let a = 10;\n    const b = 5;\n\n\n    \u002F\u002F good\n\n    var a = 10;\n    console.log(a); \u002F\u002F 10\n\n    function fun() {}\n    fun();\n\n    class A {\n    }\n    new A();\n\n    let a = 10;\n    const b = 5;\n    console.log(a); \u002F\u002F 10\n    console.log(b); \u002F\u002F 5\n    ```\n\n  - For more information refer to [JavaScript Scoping & Hoisting](https:\u002F\u002Fwww.adequatelygood.com\u002F2010\u002F2\u002FJavaScript-Scoping-and-Hoisting\u002F) by [Ben Cherry](https:\u002F\u002Fwww.adequatelygood.com\u002F).\n\n**[⬆ back to top](#table-of-contents)**\n\n## Comparison Operators & Equality\n\n  \u003Ca name=\"comparison--eqeqeq\">\u003C\u002Fa>\u003Ca name=\"15.1\">\u003C\u002Fa>\n  - [15.1](#comparison--eqeqeq) Use `===` and `!==` over `==` and `!=`. eslint: [`eqeqeq`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Feqeqeq)\n\n  \u003Ca name=\"comparison--if\">\u003C\u002Fa>\u003Ca name=\"15.2\">\u003C\u002Fa>\n  - [15.2](#comparison--if) Conditional statements such as the `if` statement evaluate their expression using coercion with the `ToBoolean` abstract method and always follow these simple rules:\n\n    - **Objects** evaluate to **true**\n    - **Undefined** evaluates to **false**\n    - **Null** evaluates to **false**\n    - **Booleans** evaluate to **the value of the boolean**\n    - **Numbers** evaluate to **false** if **+0, -0, or NaN**, otherwise **true**\n    - **Strings** evaluate to **false** if an empty string `''`, otherwise **true**\n\n    ```javascript\n    if ([0] && []) {\n      \u002F\u002F true\n      \u002F\u002F an array (even an empty one) is an object, objects will evaluate to true\n    }\n    ```\n\n  \u003Ca name=\"comparison--shortcuts\">\u003C\u002Fa>\u003Ca name=\"15.3\">\u003C\u002Fa>\n  - [15.3](#comparison--shortcuts) Use shortcuts for booleans, but explicit comparisons for strings and numbers.\n\n    ```javascript\n    \u002F\u002F bad\n    if (isValid === true) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    if (isValid) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    if (name) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    if (name !== '') {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F bad\n    if (collection.length) {\n      \u002F\u002F ...\n    }\n\n    \u002F\u002F good\n    if (collection.length > 0) {\n      \u002F\u002F ...\n    }\n    ```\n\n  \u003Ca name=\"comparison--moreinfo\">\u003C\u002Fa>\u003Ca name=\"15.4\">\u003C\u002Fa>\n  - [15.4](#comparison--moreinfo) For more information see [Truth, Equality, and JavaScript](https:\u002F\u002Fjavascriptweblog.wordpress.com\u002F2011\u002F02\u002F07\u002Ftruth-equality-and-javascript\u002F#more-2108) by Angus Croll.\n\n  \u003Ca name=\"comparison--switch-blocks\">\u003C\u002Fa>\u003Ca name=\"15.5\">\u003C\u002Fa>\n  - [15.5](#comparison--switch-blocks) Use braces to create blocks in `case` and `default` clauses that contain lexical declarations (e.g. `let`, `const`, `function`, and `class`). eslint: [`no-case-declarations`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-case-declarations)\n\n    > Why? Lexical declarations are visible in the entire `switch` block but only get initialized when assigned, which only happens when its `case` is reached. This causes problems when multiple `case` clauses attempt to define the same thing.\n\n    ```javascript\n    \u002F\u002F bad\n    switch (foo) {\n      case 1:\n        let x = 1;\n        break;\n      case 2:\n        const y = 2;\n        break;\n      case 3:\n        function f() {\n          \u002F\u002F ...\n        }\n        break;\n      default:\n        class C {}\n    }\n\n    \u002F\u002F good\n    switch (foo) {\n      case 1: {\n        let x = 1;\n        break;\n      }\n      case 2: {\n        const y = 2;\n        break;\n      }\n      case 3: {\n        function f() {\n          \u002F\u002F ...\n        }\n        break;\n      }\n      case 4:\n        bar();\n        break;\n      default: {\n        class C {}\n      }\n    }\n    ```\n\n  \u003Ca name=\"comparison--nested-ternaries\">\u003C\u002Fa>\u003Ca name=\"15.6\">\u003C\u002Fa>\n  - [15.6](#comparison--nested-ternaries) Ternaries should not be nested and generally be single line expressions. eslint: [`no-nested-ternary`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-nested-ternary)\n\n    ```javascript\n    \u002F\u002F bad\n    const foo = maybe1 > maybe2\n      ? 'bar'\n      : value1 > value2 ? 'baz' : null;\n\n    \u002F\u002F split into 2 separated ternary expressions\n    const maybeNull = value1 > value2 ? 'baz' : null;\n\n    \u002F\u002F better\n    const foo = maybe1 > maybe2\n      ? 'bar'\n      : maybeNull;\n\n    \u002F\u002F best\n    const foo = maybe1 > maybe2 ? 'bar' : maybeNull;\n    ```\n\n  \u003Ca name=\"comparison--unneeded-ternary\">\u003C\u002Fa>\u003Ca name=\"15.7\">\u003C\u002Fa>\n  - [15.7](#comparison--unneeded-ternary) Avoid unneeded ternary statements. eslint: [`no-unneeded-ternary`](https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002Fno-unneeded-ternary)\n\n    ```javascript\n    \u002F\u002F bad\n    const foo = a ? a : b;\n    const bar = c ? true : false;\n    const baz = c ? false : true;\n    const quux = a != null ? a : b;\n\n    \u002F\u002F good\n    const foo = a || b;\n    const bar = !!c;\n    const baz = !c;\n    const quux = a ?? b;\n    ```\n\n  \u003Ca name=\"comparison--no-mixed-operators\">\u003C\u002Fa>\n  - [15.8](#comparison--no-mixed-operators) When mixing operators, enclose them in parentheses. The only exception is the standard arithmetic operators: `+`, `-`, and `**` since their precedence is broadly understood. We recommend enclo","Airbnb JavaScript Style Guide 是一个用于规范JavaScript编码风格的指南。该项目提供了详尽的代码编写规则，包括变量命名、函数声明、对象与数组处理等方面，并支持ES2015+的新特性如箭头函数等。它基于ESLint配置，通过使用`babel-preset-airbnb`和相应的浏览器兼容性补丁来确保代码的一致性和可读性。适合需要统一团队开发标准、提高代码质量和维护性的场景，特别是那些已经采用或计划采用现代JavaScript特性的项目。","2026-06-17 02:33:04","top_all"]