{"id":15020726,"url":"https://github.com/leonidlebedev/javascript-airbnb","last_synced_at":"2025-05-16T15:08:00.306Z","repository":{"id":37580027,"uuid":"76608745","full_name":"leonidlebedev/javascript-airbnb","owner":"leonidlebedev","description":"Перевод «JavaScript Style Guide» от Airbnb","archived":false,"fork":false,"pushed_at":"2021-11-28T09:30:14.000Z","size":522,"stargazers_count":924,"open_issues_count":0,"forks_count":271,"subscribers_count":44,"default_branch":"master","last_synced_at":"2025-04-12T14:16:54.165Z","etag":null,"topics":["arrow-functions","es2015","es2016","es2017","es2018","es2019","es2020","es6","eslint","javascript","linting","naming-conventions","react","style-guide","style-linter","styleguide","translation"],"latest_commit_sha":null,"homepage":"https://leonidlebedev.github.io/javascript-airbnb/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leonidlebedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-16T01:01:16.000Z","updated_at":"2025-04-10T18:12:55.000Z","dependencies_parsed_at":"2022-07-12T16:24:44.285Z","dependency_job_id":null,"html_url":"https://github.com/leonidlebedev/javascript-airbnb","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidlebedev%2Fjavascript-airbnb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidlebedev%2Fjavascript-airbnb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidlebedev%2Fjavascript-airbnb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidlebedev%2Fjavascript-airbnb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leonidlebedev","download_url":"https://codeload.github.com/leonidlebedev/javascript-airbnb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254553958,"owners_count":22090417,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arrow-functions","es2015","es2016","es2017","es2018","es2019","es2020","es6","eslint","javascript","linting","naming-conventions","react","style-guide","style-linter","styleguide","translation"],"created_at":"2024-09-24T19:55:30.314Z","updated_at":"2025-05-16T15:07:55.295Z","avatar_url":"https://github.com/leonidlebedev.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Руководство по написанию JavaScript-кода от [Airbnb](https://github.com/airbnb/javascript/)() {\n\n*Наиболее разумный подход к написанию JavaScript-кода*\n\n\u003e **Замечание**: это руководство подразумевает использование [Babel](https://babeljs.io) вместе с [babel-preset-airbnb](https://npmjs.com/babel-preset-airbnb) или аналогом. Оно также предполагает установленный shims/polyfills в вашем приложении, такой как [airbnb-browser-shims](https://npmjs.com/airbnb-browser-shims) или аналог.\n\n[![Скачать](https://img.shields.io/npm/dm/eslint-config-airbnb.svg)](https://www.npmjs.com/package/eslint-config-airbnb)\n[![Скачать](https://img.shields.io/npm/dm/eslint-config-airbnb-base.svg)](https://www.npmjs.com/package/eslint-config-airbnb-base)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/airbnb/javascript?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\nЭто руководство также доступно на других языках. Смотрите [Переводы](#translation).\n\nДругие руководства\n\n  - [React](react/)\n  - [CSS-in-JavaScript](css-in-javascript/)\n\n## Оглавление\n\n  1. [Типы](#types)\n  1. [Объявление переменных](#references)\n  1. [Объекты](#objects)\n  1. [Массивы](#arrays)\n  1. [Деструктуризация](#destructuring)\n  1. [Строки](#strings)\n  1. [Функции](#functions)\n  1. [Стрелочные функции](#arrow-functions)\n  1. [Классы и конструкторы](#classes--constructors)\n  1. [Модули](#modules)\n  1. [Итераторы и генераторы](#iterators-and-generators)\n  1. [Свойства](#properties)\n  1. [Переменные](#variables)\n  1. [Подъём](#hoisting)\n  1. [Операторы сравнения и равенства](#comparison-operators--equality)\n  1. [Блоки](#blocks)\n  1. [Управляющие операторы](#control-statements)\n  1. [Комментарии](#comments)\n  1. [Пробелы](#whitespace)\n  1. [Запятые](#commas)\n  1. [Точка с запятой](#semicolons)\n  1. [Приведение типов](#type-casting--coercion)\n  1. [Соглашение об именовании](#naming-conventions)\n  1. [Аксессоры](#accessors)\n  1. [События](#events)\n  1. [jQuery](#jquery)\n  1. [Поддержка ECMAScript 5](#ecmascript-5-compatibility)\n  1. [Возможности ECMAScript 6+ (ES 2015+)](#ecmascript-6-es-2015-styles)\n  1. [Стандартная библиотека](#standard-library)\n  1. [Тестирование](#testing)\n  1. [Производительность](#performance)\n  1. [Ресурсы](#resources)\n  1. [В реальной жизни](#in-the-wild)\n  1. [Переводы](#translation)\n  1. [Пообщаться с разработчиками Airbnb](#chat-with-us-about-javascript)\n  1. [Участники перевода](#contributors)\n  1. [Лицензия](#license)\n  1. [Поправки](#amendments)\n\n## \u003ca name=\"types\"\u003eТипы\u003c/a\u003e\n\n  \u003ca name=\"types--primitives\"\u003e\u003c/a\u003e\u003ca name=\"1.1\"\u003e\u003c/a\u003e\n  - [1.1](#types--primitives) **Простые типы**: Когда вы взаимодействуете с простым типом, вы напрямую работаете с его значением.\n\n    - `string`\n    - `number`\n    - `boolean`\n    - `null`\n    - `undefined`\n    - `symbol`\n    - `bigint`\n\n    ```javascript\n    const foo = 1;\n    let bar = foo;\n\n    bar = 9;\n\n    console.log(foo, bar); // =\u003e 1, 9\n    ```\n\n    - Symbol и BigInt не могут быть полностью заполифиллены, поэтому они не должны использоваться, если разработка ведётся для браузеров или других сред, которые не поддерживают их нативно.\n\n  \u003ca name=\"types--complex\"\u003e\u003c/a\u003e\u003ca name=\"1.2\"\u003e\u003c/a\u003e\n  - [1.2](#types--complex)  **Сложные типы**: Когда вы взаимодействуете со сложным типом, вы работаете со ссылкой на его значение.\n\n    - `object`\n    - `array`\n    - `function`\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]); // =\u003e 9, 9\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"references\"\u003eОбъявление переменных\u003c/a\u003e\n\n  \u003ca name=\"references--prefer-const\"\u003e\u003c/a\u003e\u003ca name=\"2.1\"\u003e\u003c/a\u003e\n  - [2.1](#references--prefer-const) Используйте `const` для объявления переменных; избегайте `var`. eslint: [`prefer-const`](https://eslint.org/docs/rules/prefer-const.html), [`no-const-assign`](https://eslint.org/docs/rules/no-const-assign.html)\n\n    \u003e Почему? Это гарантирует, что вы не сможете переопределять значения, т.к. это может привести к ошибкам и к усложнению понимания кода.\n\n    ```javascript\n    // плохо\n    var a = 1;\n    var b = 2;\n\n    // хорошо\n    const a = 1;\n    const b = 2;\n    ```\n\n  \u003ca name=\"references--disallow-var\"\u003e\u003c/a\u003e\u003ca name=\"2.2\"\u003e\u003c/a\u003e\n  - [2.2](#references--disallow-var) Если вам необходимо переопределять значения, то используйте `let` вместо `var`. eslint: [`no-var`](https://eslint.org/docs/rules/no-var.html)\n\n    \u003e Почему? Область видимости `let` — блок, у `var` — функция.\n\n    ```javascript\n    // плохо\n    var count = 1;\n    if (true) {\n      count += 1;\n    }\n\n    // хорошо, используйте let.\n    let count = 1;\n    if (true) {\n      count += 1;\n    }\n    ```\n\n  \u003ca name=\"references--block-scope\"\u003e\u003c/a\u003e\u003ca name=\"2.3\"\u003e\u003c/a\u003e\n  - [2.3](#references--block-scope) Помните, что у `let` и `const` блочная область видимости, в то время как `var` имеет функциональную область видимости.\n\n    ```javascript\n    // const и let существуют только в том блоке, в котором они определены.\n    {\n      let a = 1;\n      const b = 1;\n      var c = 1;\n    }\n    console.log(a); // ReferenceError\n    console.log(b); // ReferenceError\n    console.log(c); // 1\n    ```\n\n    В приведённом выше коде вы можете видеть, что ссылки на `a` и `b` приведут к ошибке `ReferenceError`, в то время как `c` содержит число. Это связано с тем, что `a` и `b` имеют блочную область видимости, в то время как у `c` функциональная.\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"objects\"\u003eОбъекты\u003c/a\u003e\n\n  \u003ca name=\"objects--no-new\"\u003e\u003c/a\u003e\u003ca name=\"3.1\"\u003e\u003c/a\u003e\n  - [3.1](#objects--no-new) Для создания объекта используйте литеральную нотацию. eslint: [`no-new-object`](https://eslint.org/docs/rules/no-new-object.html)\n\n    ```javascript\n    // плохо\n    const item = new Object();\n\n    // хорошо\n    const item = {};\n    ```\n\n  \u003ca name=\"es6-computed-properties\"\u003e\u003c/a\u003e\u003ca name=\"3.4\"\u003e\u003c/a\u003e\n  - [3.2](#es6-computed-properties) Используйте вычисляемые имена свойств, когда создаёте объекты с динамическими именами свойств.\n\n    \u003e Почему? Они позволяют вам определить все свойства объекта в одном месте.\n\n    ```javascript\n\n    function getKey(k) {\n      return `a key named ${k}`;\n    }\n\n    // плохо\n    const obj = {\n      id: 5,\n      name: 'San Francisco',\n    };\n    obj[getKey('enabled')] = true;\n\n    // хорошо\n    const obj = {\n      id: 5,\n      name: 'San Francisco',\n      [getKey('enabled')]: true,\n    };\n    ```\n\n  \u003ca name=\"es6-object-shorthand\"\u003e\u003c/a\u003e\u003ca name=\"3.5\"\u003e\u003c/a\u003e\n  - [3.3](#es6-object-shorthand) Используйте сокращённую запись метода объекта. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand.html)\n\n    ```javascript\n    // плохо\n    const atom = {\n      value: 1,\n\n      addValue: function (value) {\n        return atom.value + value;\n      },\n    };\n\n    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"3.6\"\u003e\u003c/a\u003e\n  - [3.4](#es6-object-concise) Используйте сокращённую запись свойств объекта. eslint: [`object-shorthand`](https://eslint.org/docs/rules/object-shorthand.html)\n\n    \u003e Почему? Это короче и понятнее.\n\n    ```javascript\n    const lukeSkywalker = 'Luke Skywalker';\n\n    // плохо\n    const obj = {\n      lukeSkywalker: lukeSkywalker,\n    };\n\n    // хорошо\n    const obj = {\n      lukeSkywalker,\n    };\n    ```\n\n  \u003ca name=\"objects--grouped-shorthand\"\u003e\u003c/a\u003e\u003ca name=\"3.7\"\u003e\u003c/a\u003e\n  - [3.5](#objects--grouped-shorthand) Группируйте ваши сокращённые записи свойств в начале объявления объекта.\n\n    \u003e Почему? Так легче сказать, какие свойства используют сокращённую запись.\n\n    ```javascript\n    const anakinSkywalker = 'Anakin Skywalker';\n    const lukeSkywalker = 'Luke Skywalker';\n\n    // плохо\n    const obj = {\n      episodeOne: 1,\n      twoJediWalkIntoACantina: 2,\n      lukeSkywalker,\n      episodeThree: 3,\n      mayTheFourth: 4,\n      anakinSkywalker,\n    };\n\n    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"3.8\"\u003e\u003c/a\u003e\n  - [3.6](#objects--quoted-props) Только недопустимые идентификаторы помещаются в кавычки. eslint: [`quote-props`](https://eslint.org/docs/rules/quote-props.html)\n\n    \u003e Почему? На наш взгляд, такой код легче читать. Это улучшает подсветку синтаксиса, а также облегчает оптимизацию для многих JS-движков.\n\n    ```javascript\n    // плохо\n    const bad = {\n      'foo': 3,\n      'bar': 4,\n      'data-blah': 5,\n    };\n\n    // хорошо\n    const good = {\n      foo: 3,\n      bar: 4,\n      'data-blah': 5,\n    };\n    ```\n\n  \u003ca name=\"objects--prototype-builtins\"\u003e\u003c/a\u003e\n  - [3.7](#objects--prototype-builtins) Не вызывайте напрямую методы `Object.prototype`, такие как `hasOwnProperty`, `propertyIsEnumerable`, и `isPrototypeOf`. eslint: [`no-prototype-builtins`](https://eslint.org/docs/rules/no-prototype-builtins)\n\n    \u003e Почему? Эти методы могут быть переопределены в свойствах объекта, который мы проверяем `{ hasOwnProperty: false }`, или этот объект может быть `null` (`Object.create(null)`).\n\n    ```javascript\n    // плохо\n    console.log(object.hasOwnProperty(key));\n\n    // хорошо\n    console.log(Object.prototype.hasOwnProperty.call(object, key));\n\n    // отлично\n    const has = Object.prototype.hasOwnProperty; // Кэшируем запрос в рамках модуля.\n    console.log(has.call(object, key));\n    /* или */\n    import has from 'has'; // https://www.npmjs.com/package/has\n    console.log(has(object, key));\n    ```\n\n  \u003ca name=\"objects--rest-spread\"\u003e\u003c/a\u003e\n  - [3.8](#objects--rest-spread) Используйте синтаксис расширения вместо [`Object.assign`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) для поверхностного копирования объектов. Используйте параметр оставшихся свойств, чтобы получить новый объект с некоторыми опущенными свойствами. eslint: [`prefer-object-spread`](https://eslint.org/docs/rules/prefer-object-spread)\n\n    ```javascript\n    // очень плохо\n    const original = { a: 1, b: 2 };\n    const copy = Object.assign(original, { c: 3 }); // эта переменная изменяет `original` ಠ_ಠ\n    delete copy.a; // если сделать так\n\n    // плохо\n    const original = { a: 1, b: 2 };\n    const copy = Object.assign({}, original, { c: 3 }); // copy =\u003e { a: 1, b: 2, c: 3 }\n\n    // хорошо\n    const original = { a: 1, b: 2 };\n    const copy = { ...original, c: 3 }; // copy =\u003e { a: 1, b: 2, c: 3 }\n\n    const { a, ...noA } = copy; // noA =\u003e { b: 2, c: 3 }\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"arrays\"\u003eМассивы\u003c/a\u003e\n\n  \u003ca name=\"arrays--literals\"\u003e\u003c/a\u003e\u003ca name=\"4.1\"\u003e\u003c/a\u003e\n  - [4.1](#arrays--literals) Для создания массива используйте литеральную нотацию. eslint: [`no-array-constructor`](https://eslint.org/docs/rules/no-array-constructor.html)\n\n    ```javascript\n    // плохо\n    const items = new Array();\n\n    // хорошо\n    const items = [];\n    ```\n\n  \u003ca name=\"arrays--push\"\u003e\u003c/a\u003e\u003ca name=\"4.2\"\u003e\u003c/a\u003e\n  - [4.2](#arrays--push) Для добавления элемента в массив используйте [Array#push](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/push) вместо прямого присваивания.\n\n    ```javascript\n    const someStack = [];\n\n    // плохо\n    someStack[someStack.length] = 'abracadabra';\n\n    // хорошо\n    someStack.push('abracadabra');\n    ```\n\n  \u003ca name=\"es6-array-spreads\"\u003e\u003c/a\u003e\u003ca name=\"4.3\"\u003e\u003c/a\u003e\n  - [4.3](#es6-array-spreads) Для копирования массивов используйте оператор расширения `...`.\n\n    ```javascript\n    // плохо\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    // хорошо\n    const itemsCopy = [...items];\n    ```\n\n  \u003ca name=\"arrays--from\"\u003e\u003c/a\u003e\n  \u003ca name=\"arrays--from-iterable\"\u003e\u003c/a\u003e\u003ca name=\"4.4\"\u003e\u003c/a\u003e\n  - [4.4](#arrays--from-iterable) Для преобразования итерируемого объекта в массив используйте оператор расширения `...` вместо [`Array.from`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/from).\n\n    ```javascript\n    const foo = document.querySelectorAll('.foo');\n\n    // хорошо\n    const nodes = Array.from(foo);\n\n    // отлично\n    const nodes = [...foo];\n    ```\n\n  \u003ca name=\"arrays--from-array-like\"\u003e\u003c/a\u003e\n  - [4.5](#arrays--from-array-like) Используйте [`Array.from`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/from) для преобразования массивоподобного объекта в массив.\n\n    ```javascript\n    const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };\n\n    // плохо\n    const arr = Array.prototype.slice.call(arrLike);\n\n    // хорошо\n    const arr = Array.from(arrLike);\n    ```\n\n  \u003ca name=\"arrays--mapping\"\u003e\u003c/a\u003e\n  - [4.6](#arrays--mapping) Используйте [`Array.from`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/from) вместо оператора расширения `...` для маппинга итерируемых объектов, это позволяет избежать создания промежуточного массива.\n\n    ```javascript\n    // плохо\n    const baz = [...foo].map(bar);\n\n    // хорошо\n    const baz = Array.from(foo, bar);\n    ```\n\n  \u003ca name=\"arrays--callback-return\"\u003e\u003c/a\u003e\u003ca name=\"4.5\"\u003e\u003c/a\u003e\n  - [4.7](#arrays--callback-return) Используйте операторы `return` внутри функций обратного вызова в методах массива. Можно опустить `return`, когда тело функции состоит из одной инструкции, возвращающей выражение без побочных эффектов. [8.2](#arrows--implicit-return). eslint: [`array-callback-return`](https://eslint.org/docs/rules/array-callback-return)\n\n    ```javascript\n    // хорошо\n    [1, 2, 3].map((x) =\u003e {\n      const y = x + 1;\n      return x * y;\n    });\n\n    // хорошо\n    [1, 2, 3].map((x) =\u003e x + 1);\n\n    // плохо - нет возвращаемого значения, следовательно, `acc` становится `undefined` после первой итерации\n    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) =\u003e {\n      const flatten = acc.concat(item);\n    });\n\n    // хорошо\n    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) =\u003e {\n      const flatten = acc.concat(item);\n      return flatten;\n    });\n\n    // плохо\n    inbox.filter((msg) =\u003e {\n      const { subject, author } = msg;\n      if (subject === 'Mockingbird') {\n        return author === 'Harper Lee';\n      } else {\n        return false;\n      }\n    });\n\n    // хорошо\n    inbox.filter((msg) =\u003e {\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\"\u003e\u003c/a\u003e\n  - [4.8](#arrays--bracket-newline) Если массив располагается на нескольких строках, то используйте разрывы строк после открытия и перед закрытием скобок.\n\n    ```javascript\n    // плохо\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    // хорошо\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**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"destructuring\"\u003eДеструктуризация\u003c/a\u003e\n\n  \u003ca name=\"destructuring--object\"\u003e\u003c/a\u003e\u003ca name=\"5.1\"\u003e\u003c/a\u003e\n  - [5.1](#destructuring--object) При обращении к нескольким свойствам объекта используйте деструктуризацию объекта. eslint: [`prefer-destructuring`](https://eslint.org/docs/rules/prefer-destructuring)\n\n    \u003e Почему? Деструктуризация сохраняет вас от создания временных переменных для этих свойств и от повторного доступа к объекту. Повторный доступ к объектам создаёт более повторяющийся код, требует большего чтения и создаёт больше возможностей для ошибок. Деструктуризация объектов также обеспечивает единое местоположение определения структуры объекта, которое используется в блоке, вместо того, чтобы требовать чтения всего блока для определения того, что используется.\n\n    ```javascript\n    // плохо\n    function getFullName(user) {\n      const firstName = user.firstName;\n      const lastName = user.lastName;\n\n      return `${firstName} ${lastName}`;\n    }\n\n    // хорошо\n    function getFullName(user) {\n      const { firstName, lastName } = user;\n      return `${firstName} ${lastName}`;\n    }\n\n    // отлично\n    function getFullName({ firstName, lastName }) {\n      return `${firstName} ${lastName}`;\n    }\n    ```\n\n  \u003ca name=\"destructuring--array\"\u003e\u003c/a\u003e\u003ca name=\"5.2\"\u003e\u003c/a\u003e\n  - [5.2](#destructuring--array) Используйте деструктуризацию массивов. eslint: [`prefer-destructuring`](https://eslint.org/docs/rules/prefer-destructuring)\n\n    ```javascript\n    const arr = [1, 2, 3, 4];\n\n    // плохо\n    const first = arr[0];\n    const second = arr[1];\n\n    // хорошо\n    const [first, second] = arr;\n    ```\n\n  \u003ca name=\"destructuring--object-over-array\"\u003e\u003c/a\u003e\u003ca name=\"5.3\"\u003e\u003c/a\u003e\n  - [5.3](#destructuring--object-over-array) Используйте деструктуризацию объекта для множества возвращаемых значений, но не делайте тоже самое с массивами.\n\n    \u003e Почему? Вы сможете добавить новые свойства через некоторое время или изменить порядок без последствий.\n\n    ```javascript\n    // плохо\n    function processInput(input) {\n      // затем происходит чудо\n      return [left, right, top, bottom];\n    }\n\n    // при вызове нужно подумать о порядке возвращаемых данных\n    const [left, __, top] = processInput(input);\n\n    // хорошо\n    function processInput(input) {\n      // затем происходит чудо\n      return { left, right, top, bottom };\n    }\n\n    // при вызове выбираем только необходимые данные\n    const { left, top } = processInput(input);\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"strings\"\u003eСтроки\u003c/a\u003e\n\n  \u003ca name=\"strings--quotes\"\u003e\u003c/a\u003e\u003ca name=\"6.1\"\u003e\u003c/a\u003e\n  - [6.1](#strings--quotes) Используйте одинарные кавычки `''` для строк. eslint: [`quotes`](https://eslint.org/docs/rules/quotes.html)\n\n    ```javascript\n    // плохо\n    const name = \"Capt. Janeway\";\n\n    // плохо - литерал шаблонной строки должен содержать интерполяцию или переводы строк\n    const name = `Capt. Janeway`;\n\n    // хорошо\n    const name = 'Capt. Janeway';\n    ```\n\n  \u003ca name=\"strings--line-length\"\u003e\u003c/a\u003e\u003ca name=\"6.2\"\u003e\u003c/a\u003e\n  - [6.2](#strings--line-length) Строки, у которых в строчке содержится более 100 символов, не пишутся на нескольких строчках с использованием конкатенации.\n\n    \u003e Почему? Работать с разбитыми строками неудобно и это затрудняет поиск по коду.\n\n    ```javascript\n    // плохо\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    // плохо\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    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"6.4\"\u003e\u003c/a\u003e\n  - [6.3](#es6-template-literals) При создании строки программным путём используйте шаблонные строки вместо конкатенации. eslint: [`prefer-template`](https://eslint.org/docs/rules/prefer-template.html) [`template-curly-spacing`](https://eslint.org/docs/rules/template-curly-spacing)\n\n    \u003e Почему? Шаблонные строки дают вам читабельность, лаконичный синтаксис с правильными символами перевода строк и функции интерполяции строки.\n\n    ```javascript\n    // плохо\n    function sayHi(name) {\n      return 'How are you, ' + name + '?';\n    }\n\n    // плохо\n    function sayHi(name) {\n      return ['How are you, ', name, '?'].join();\n    }\n\n    // плохо\n    function sayHi(name) {\n      return `How are you, ${ name }?`;\n    }\n\n    // хорошо\n    function sayHi(name) {\n      return `How are you, ${name}?`;\n    }\n    ```\n\n  \u003ca name=\"strings--eval\"\u003e\u003c/a\u003e\u003ca name=\"6.5\"\u003e\u003c/a\u003e\n  - [6.4](#strings--eval) Никогда не используйте `eval()`, т.к. это открывает множество уязвимостей. eslint: [`no-eval`](https://eslint.org/docs/rules/no-eval)\n\n  \u003ca name=\"strings--escaping\"\u003e\u003c/a\u003e\n  - [6.5](#strings--escaping) Не используйте в строках необязательные экранирующие символы. eslint: [`no-useless-escape`](https://eslint.org/docs/rules/no-useless-escape)\n\n    \u003e Почему? Обратные слеши ухудшают читабельность, поэтому они должны быть только при необходимости.\n\n    ```javascript\n    // плохо\n    const foo = '\\'this\\' \\i\\s \\\"quoted\\\"';\n\n    // хорошо\n    const foo = '\\'this\\' is \"quoted\"';\n    const foo = `my name is '${name}'`;\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"functions\"\u003eФункции\u003c/a\u003e\n\n  \u003ca name=\"functions--declarations\"\u003e\u003c/a\u003e\u003ca name=\"7.1\"\u003e\u003c/a\u003e\n  - [7.1](#functions--declarations) Используйте функциональные выражения вместо объявлений функций. eslint: [`func-style`](https://eslint.org/docs/rules/func-style)\n\n    \u003e Почему? У объявлений функций есть подъём. Это означает, что можно использовать функцию до того, как она определена в файле, но это вредит читабельности и поддержке. Если вы обнаружили, что определение функции настолько большое или сложное, что мешает понимать остальную часть файла, то, возможно, пришло время извлечь его в отдельный модуль. Не забудьте явно назвать функциональное выражение, независимо от того, подразумевается ли имя из содержащейся переменной (такое часто бывает в современных браузерах или при использовании компиляторов, таких как Babel). Это помогает точнее определять место ошибки по стеку вызовов. ([Обсуждение](https://github.com/airbnb/javascript/issues/794))\n\n    ```javascript\n    // плохо\n    function foo() {\n      // ...\n    }\n\n    // плохо\n    const foo = function () {\n      // ...\n    };\n\n    // хорошо\n    // лексическое имя, отличное от вызываемой(-ых) переменной(-ых)\n    const foo = function uniqueMoreDescriptiveLexicalFoo() {\n      // ...\n    };\n    ```\n\n  \u003ca name=\"functions--iife\"\u003e\u003c/a\u003e\u003ca name=\"7.2\"\u003e\u003c/a\u003e\n  - [7.2](#functions--iife) Оборачивайте в скобки немедленно вызываемые функции. eslint: [`wrap-iife`](https://eslint.org/docs/rules/wrap-iife.html)\n\n    \u003e Почему? Немедленно вызываемая функция представляет собой единый блок. Чтобы чётко показать это — оберните функцию и вызывающие скобки в ещё одни скобки. Обратите внимание, что в мире с модулями вам больше не нужны немедленно вызываемые функции.\n\n    ```javascript\n    // Немедленно вызываемая функция\n    (function () {\n      console.log('Welcome to the Internet. Please follow me.');\n    }());\n    ```\n\n  \u003ca name=\"functions--in-blocks\"\u003e\u003c/a\u003e\u003ca name=\"7.3\"\u003e\u003c/a\u003e\n  - [7.3](#functions--in-blocks) Никогда не объявляйте функции в нефункциональном блоке (`if`, `while`, и т.д.). Вместо этого присвойте функцию переменной. Браузеры позволяют выполнить ваш код, но все они интерпретируют его по-разному. eslint: [`no-loop-func`](https://eslint.org/docs/rules/no-loop-func.html)\n\n  \u003ca name=\"functions--note-on-blocks\"\u003e\u003c/a\u003e\u003ca name=\"7.4\"\u003e\u003c/a\u003e\n  - [7.4](#functions--note-on-blocks) **Примечание:** ECMA-262 определяет `блок` как список инструкций. Объявление функции не является инструкцией.\n\n    ```javascript\n    // плохо\n    if (currentUser) {\n      function test() {\n        console.log('Nope.');\n      }\n    }\n\n    // хорошо\n    let test;\n    if (currentUser) {\n      test = () =\u003e {\n        console.log('Yup.');\n      };\n    }\n    ```\n\n  \u003ca name=\"functions--arguments-shadow\"\u003e\u003c/a\u003e\u003ca name=\"7.5\"\u003e\u003c/a\u003e\n  - [7.5](#functions--arguments-shadow) Никогда не называйте параметр `arguments`. Он будет иметь приоритет над объектом `arguments`, который доступен для каждой функции.\n\n    ```javascript\n    // плохо\n    function foo(name, options, arguments) {\n      // ...\n    }\n\n    // хорошо\n    function foo(name, options, args) {\n      // ...\n    }\n    ```\n\n  \u003ca name=\"es6-rest\"\u003e\u003c/a\u003e\u003ca name=\"7.6\"\u003e\u003c/a\u003e\n  - [7.6](#es6-rest) Никогда не используйте `arguments`, вместо этого используйте синтаксис оставшихся параметров `...`. eslint: [`prefer-rest-params`](https://eslint.org/docs/rules/prefer-rest-params)\n\n    \u003e Почему? `...` явно говорит о том, какие именно аргументы вы хотите извлечь. Кроме того, такой синтаксис создаёт настоящий массив, а не массивоподобный объект как `arguments`.\n\n    ```javascript\n    // плохо\n    function concatenateAll() {\n      const args = Array.prototype.slice.call(arguments);\n      return args.join('');\n    }\n\n    // хорошо\n    function concatenateAll(...args) {\n      return args.join('');\n    }\n    ```\n\n  \u003ca name=\"es6-default-parameters\"\u003e\u003c/a\u003e\u003ca name=\"7.7\"\u003e\u003c/a\u003e\n  - [7.7](#es6-default-parameters) Используйте синтаксис записи аргументов по умолчанию, а не изменяйте аргументы функции.\n\n    ```javascript\n    // очень плохо\n    function handleThings(opts) {\n      // Нет! Мы не должны изменять аргументы функции.\n      // Плохо вдвойне: если переменная opts будет ложной,\n      // то ей присвоится пустой объект, а не то что вы хотели.\n      // Это приведёт к коварным ошибкам.\n      opts = opts || {};\n      // ...\n    }\n\n    // всё ещё плохо\n    function handleThings(opts) {\n      if (opts === void 0) {\n        opts = {};\n      }\n      // ...\n    }\n\n    // хорошо\n    function handleThings(opts = {}) {\n      // ...\n    }\n    ```\n\n  \u003ca name=\"functions--default-side-effects\"\u003e\u003c/a\u003e\u003ca name=\"7.8\"\u003e\u003c/a\u003e\n  - [7.8](#functions--default-side-effects) Избегайте побочных эффектов с параметрами по умолчанию.\n\n    \u003e Почему? И так всё понятно.\n\n    ```javascript\n    var b = 1;\n    // плохо\n    function count(a = b++) {\n      console.log(a);\n    }\n    count();  // 1\n    count();  // 2\n    count(3); // 3\n    count();  // 3\n    ```\n\n  \u003ca name=\"functions--defaults-last\"\u003e\u003c/a\u003e\u003ca name=\"7.9\"\u003e\u003c/a\u003e\n  - [7.9](#functions--defaults-last) Всегда вставляйте последними параметры по умолчанию. eslint: [`default-param-last`](https://eslint.org/docs/rules/default-param-last)\n\n    ```javascript\n    // плохо\n    function handleThings(opts = {}, name) {\n      // ...\n    }\n\n    // хорошо\n    function handleThings(name, opts = {}) {\n      // ...\n    }\n    ```\n\n  \u003ca name=\"functions--constructor\"\u003e\u003c/a\u003e\u003ca name=\"7.10\"\u003e\u003c/a\u003e\n  - [7.10](#functions--constructor) Никогда не используйте конструктор функций для создания новых функий. eslint: [`no-new-func`](https://eslint.org/docs/rules/no-new-func)\n\n    \u003e Почему? Создание функции в таком духе вычисляет строку подобно `eval()`, из-за чего открываются уязвимости.\n\n    ```javascript\n    // плохо\n    var add = new Function('a', 'b', 'return a + b');\n\n    // всё ещё плохо\n    var subtract = Function('a', 'b', 'return a - b');\n    ```\n\n  \u003ca name=\"functions--signature-spacing\"\u003e\u003c/a\u003e\u003ca name=\"7.11\"\u003e\u003c/a\u003e\n  - [7.11](#functions--signature-spacing) Отступы при определении функции. eslint: [`space-before-function-paren`](https://eslint.org/docs/rules/space-before-function-paren) [`space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks)\n\n    \u003e Почему? Однородность кода — это хорошо. Вам не надо будет добавлять или удалять пробел при манипуляции с именем.\n\n    ```javascript\n    // плохо\n    const f = function(){};\n    const g = function (){};\n    const h = function() {};\n\n    // хорошо\n    const x = function () {};\n    const y = function a() {};\n    ```\n\n  \u003ca name=\"functions--mutate-params\"\u003e\u003c/a\u003e\u003ca name=\"7.12\"\u003e\u003c/a\u003e\n  - [7.12](#functions--mutate-params) Никогда не изменяйте параметры. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign.html)\n\n    \u003e Почему? Манипуляция объектами, приходящими в качестве параметров, может вызывать нежелательные побочные эффекты в вызывающей функции.\n\n    ```javascript\n    // плохо\n    function f1(obj) {\n      obj.key = 1;\n    }\n\n    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"7.13\"\u003e\u003c/a\u003e\n  - [7.13](#functions--reassign-params) Никогда не переназначайте параметры. eslint: [`no-param-reassign`](https://eslint.org/docs/rules/no-param-reassign.html)\n\n    \u003e Почему? Переназначенные параметры могут привести к неожиданному поведению, особенно при обращении к `arguments`. Это также может вызывать проблемы оптимизации, особенно в V8.\n\n    ```javascript\n    // плохо\n    function f1(a) {\n      a = 1;\n      // ...\n    }\n\n    function f2(a) {\n      if (!a) { a = 1; }\n      // ...\n    }\n\n    // хорошо\n    function f3(a) {\n      const b = a || 1;\n      // ...\n    }\n\n    function f4(a = 1) {\n      // ...\n    }\n    ```\n\n  \u003ca name=\"functions--spread-vs-apply\"\u003e\u003c/a\u003e\u003ca name=\"7.14\"\u003e\u003c/a\u003e\n  - [7.14](#functions--spread-vs-apply) Отдавайте предпочтение использованию синтаксис расширения `...` при вызове вариативной функции. eslint: [`prefer-spread`](https://eslint.org/docs/rules/prefer-spread)\n\n    \u003e Почему? Это чище, вам не нужно предоставлять контекст, и не так просто составить `new` с `apply`.\n\n    ```javascript\n    // плохо\n    const x = [1, 2, 3, 4, 5];\n    console.log.apply(console, x);\n\n    // хорошо\n    const x = [1, 2, 3, 4, 5];\n    console.log(...x);\n\n    // плохо\n    new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));\n\n    // хорошо\n    new Date(...[2016, 8, 5]);\n    ```\n\n  \u003ca name=\"functions--signature-invocation-indentation\"\u003e\u003c/a\u003e\n  - [7.15](#functions--signature-invocation-indentation) Функции с многострочным определением или запуском должны содержать такие же отступы, как и другие многострочные списки в этом руководстве: с каждым элементом на отдельной строке, с запятой в конце элемента. eslint: [`function-paren-newline`](https://eslint.org/docs/rules/function-paren-newline)\n\n    ```javascript\n    // плохо\n    function foo(bar,\n                 baz,\n                 quux) {\n      // ...\n    }\n\n    // хорошо\n    function foo(\n      bar,\n      baz,\n      quux,\n    ) {\n      // ...\n    }\n\n    // плохо\n    console.log(foo,\n      bar,\n      baz);\n\n    // хорошо\n    console.log(\n      foo,\n      bar,\n      baz,\n    );\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"arrow-functions\"\u003eСтрелочные функции\u003c/a\u003e\n\n  \u003ca name=\"arrows--use-them\"\u003e\u003c/a\u003e\u003ca name=\"8.1\"\u003e\u003c/a\u003e\n  - [8.1](#arrows--use-them) Когда вам необходимо использовать анонимную функцию (например, при передаче встроенной функции обратного вызова), используйте стрелочную функцию. eslint: [`prefer-arrow-callback`](https://eslint.org/docs/rules/prefer-arrow-callback.html), [`arrow-spacing`](https://eslint.org/docs/rules/arrow-spacing.html)\n\n    \u003e Почему? Таким образом создаётся функция, которая выполняется в контексте `this`, который мы обычно хотим, а также это более короткий синтаксис.\n\n    \u003e Почему бы и нет? Если у вас есть довольно сложная функция, вы можете переместить эту логику внутрь её собственного именованного функционального выражения.\n\n    ```javascript\n    // плохо\n    [1, 2, 3].map(function (x) {\n      const y = x + 1;\n      return x * y;\n    });\n\n    // хорошо\n    [1, 2, 3].map((x) =\u003e {\n      const y = x + 1;\n      return x * y;\n    });\n    ```\n\n  \u003ca name=\"arrows--implicit-return\"\u003e\u003c/a\u003e\u003ca name=\"8.2\"\u003e\u003c/a\u003e\n  - [8.2](#arrows--implicit-return) Если тело функции состоит из одного оператора, возвращающего [выражение](https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Expressions_and_Operators#Выражения) без побочных эффектов, то опустите фигурные скобки и используйте неявное возвращение. В противном случае, сохраните фигурные скобки и используйте оператор `return`. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html), [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style.html)\n\n    \u003e Почему? Синтаксический сахар. Когда несколько функций соединены вместе, то это лучше читается.\n\n    ```javascript\n    // плохо\n    [1, 2, 3].map((number) =\u003e {\n      const nextNumber = number + 1;\n      `A string containing the ${nextNumber}.`;\n    });\n\n    // хорошо\n    [1, 2, 3].map((number) =\u003e `A string containing the ${number + 1}.`);\n\n    // хорошо\n    [1, 2, 3].map((number) =\u003e {\n      const nextNumber = number + 1;\n      return `A string containing the ${nextNumber}.`;\n    });\n\n    // хорошо\n    [1, 2, 3].map((number, index) =\u003e ({\n      [index]: number,\n    }));\n\n    // Неявный возврат с побочными эффектами\n    function foo(callback) {\n      const val = callback();\n      if (val === true) {\n        // Сделать что-то, если функция обратного вызова вернёт true\n      }\n    }\n\n    let bool = false;\n\n    // плохо\n    foo(() =\u003e bool = true);\n\n    // хорошо\n    foo(() =\u003e {\n      bool = true;\n    });\n    ```\n\n  \u003ca name=\"arrows--paren-wrap\"\u003e\u003c/a\u003e\u003ca name=\"8.3\"\u003e\u003c/a\u003e\n  - [8.3](#arrows--paren-wrap) В случае, если выражение располагается на нескольких строках, то необходимо обернуть его в скобки для лучшей читаемости.\n\n    \u003e Почему? Это чётко показывает, где функция начинается и где заканчивается.\n\n    ```javascript\n    // плохо\n    ['get', 'post', 'put'].map((httpMethod) =\u003e Object.prototype.hasOwnProperty.call(\n        httpMagicObjectWithAVeryLongName,\n        httpMethod,\n      )\n    );\n\n    // хорошо\n    ['get', 'post', 'put'].map((httpMethod) =\u003e (\n      Object.prototype.hasOwnProperty.call(\n        httpMagicObjectWithAVeryLongName,\n        httpMethod,\n      )\n    ));\n    ```\n\n  \u003ca name=\"arrows--one-arg-parens\"\u003e\u003c/a\u003e\u003ca name=\"8.4\"\u003e\u003c/a\u003e\n  - [8.4](#arrows--one-arg-parens) Всегда оборачивайте аргументы круглыми скобками для ясности и согласованности. eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html)\n    \u003e Почему? Минимизирует различия при удалении или добавлении аргументов.\n\n    ```javascript\n    // плохо\n    [1, 2, 3].map(x =\u003e x * x);\n\n    // хорошо\n    [1, 2, 3].map((x) =\u003e x * x);\n\n    // плохо\n    [1, 2, 3].map(number =\u003e (\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    // хорошо\n    [1, 2, 3].map((number) =\u003e (\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    // плохо\n    [1, 2, 3].map(x =\u003e {\n      const y = x + 1;\n      return x * y;\n    });\n\n    // хорошо\n    [1, 2, 3].map((x) =\u003e {\n      const y = x + 1;\n      return x * y;\n    });\n    ```\n\n  \u003ca name=\"arrows--confusing\"\u003e\u003c/a\u003e\u003ca name=\"8.5\"\u003e\u003c/a\u003e\n  - [8.5](#arrows--confusing) Избегайте схожести стрелочной функции (`=\u003e`) с операторами сравнения (`\u003c=`, `\u003e=`). eslint: [`no-confusing-arrow`](https://eslint.org/docs/rules/no-confusing-arrow)\n\n    ```javascript\n    // плохо\n    const itemHeight = (item) =\u003e item.height \u003c= 256 ? item.largeSize : item.smallSize;\n\n    // плохо\n    const itemHeight = (item) =\u003e item.height \u003e= 256 ? item.largeSize : item.smallSize;\n\n    // хорошо\n    const itemHeight = (item) =\u003e (item.height \u003c= 256 ? item.largeSize : item.smallSize);\n\n    // хорошо\n    const itemHeight = (item) =\u003e {\n      const { height, largeSize, smallSize } = item;\n      return height \u003c= 256 ? largeSize : smallSize;\n    };\n    ```\n\n  \u003ca name=\"whitespace--implicit-arrow-linebreak\"\u003e\u003c/a\u003e\n  - [8.6](#whitespace--implicit-arrow-linebreak) Зафиксируйте расположение тела стрелочной функции с неявным возвратом. eslint: [`implicit-arrow-linebreak`](https://eslint.org/docs/rules/implicit-arrow-linebreak)\n\n    ```javascript\n    // плохо\n    (foo) =\u003e\n      bar;\n    (foo) =\u003e\n      (bar);\n\n    // хорошо\n    (foo) =\u003e bar;\n    (foo) =\u003e (bar);\n    (foo) =\u003e (\n       bar\n    )\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"classes--constructors\"\u003eКлассы и конструкторы\u003c/a\u003e\n\n  \u003ca name=\"constructors--use-class\"\u003e\u003c/a\u003e\u003ca name=\"9.1\"\u003e\u003c/a\u003e\n  - [9.1](#constructors--use-class) Всегда используйте `class`. Избегайте прямых манипуляций с `prototype`.\n\n    \u003e Почему? Синтаксис `class` является кратким и понятным.\n\n    ```javascript\n    // плохо\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    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"9.2\"\u003e\u003c/a\u003e\n  - [9.2](#constructors--extends) Используйте `extends` для наследования.\n\n    \u003e Почему? Это встроенный способ наследовать функциональность прототипа, не нарушая `instanceof`.\n\n    ```javascript\n    // плохо\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    // хорошо\n    class PeekableQueue extends Queue {\n      peek() {\n        return this.queue[0];\n      }\n    }\n    ```\n\n  \u003ca name=\"constructors--chaining\"\u003e\u003c/a\u003e\u003ca name=\"9.3\"\u003e\u003c/a\u003e\n  - [9.3](#constructors--chaining) Методы могут возвращать `this`, чтобы делать цепочки вызовов.\n\n    ```javascript\n    // плохо\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(); // =\u003e true\n    luke.setHeight(20); // =\u003e undefined\n\n    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"9.4\"\u003e\u003c/a\u003e\n  - [9.4](#constructors--tostring) Вы можете определить свой собственный метод `toString()`, просто убедитесь, что он успешно работает и не создаёт никаких побочных эффектов.\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\"\u003e\u003c/a\u003e\u003ca name=\"9.5\"\u003e\u003c/a\u003e\n  - [9.5](#constructors--no-useless) У классов есть конструктор по умолчанию, если он не задан явно. Можно опустить пустой конструктор или конструктор, который только делегирует выполнение родительскому классу. eslint: [`no-useless-constructor`](https://eslint.org/docs/rules/no-useless-constructor)\n\n    ```javascript\n    // плохо\n    class Jedi {\n      constructor() {}\n\n      getName() {\n        return this.name;\n      }\n    }\n\n    // плохо\n    class Rey extends Jedi {\n      constructor(...args) {\n        super(...args);\n      }\n    }\n\n    // хорошо\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\"\u003e\u003c/a\u003e\n  - [9.6](#classes--no-duplicate-members) Избегайте дублирующих членов класса. eslint: [`no-dupe-class-members`](https://eslint.org/docs/rules/no-dupe-class-members)\n\n    \u003e Почему? Если объявление члена класса повторяется, без предупреждения будет использовано последнее. Наличие дубликатов скорее всего приведёт к ошибке.\n\n    ```javascript\n    // плохо\n    class Foo {\n      bar() { return 1; }\n      bar() { return 2; }\n    }\n\n    // хорошо\n    class Foo {\n      bar() { return 1; }\n    }\n\n    // хорошо\n    class Foo {\n      bar() { return 2; }\n    }\n    ```\n\n  \u003ca name=\"classes--methods-use-this\"\u003e\u003c/a\u003e\n  - [9.7](#classes--methods-use-this) Метод класса должен использовать `this` или быть преобразованным в статический метод, если только внешняя библиотека или фреймворк не требуют использования определённых нестатических методов. Будучи методом экземпляра, следует указать, что он ведёт себя по-разному в зависимости от свойств получателя. eslint: [`class-methods-use-this`](https://eslint.org/docs/rules/class-methods-use-this)\n\n    ```javascript\n    // плохо\n    class Foo {\n      bar() {\n        console.log('bar');\n      }\n    }\n    // хорошо - используется this\n    class Foo {\n      bar() {\n        console.log(this.bar);\n      }\n    }\n    // хорошо - конструктор освобождается\n    class Foo {\n      constructor() {\n        // ...\n      }\n    }\n    // хорошо - статические методы не должны использовать this\n    class Foo {\n      static bar() {\n        console.log('bar');\n      }\n    }\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"modules\"\u003eМодули\u003c/a\u003e\n\n  \u003ca name=\"modules--use-them\"\u003e\u003c/a\u003e\u003ca name=\"10.1\"\u003e\u003c/a\u003e\n  - [10.1](#modules--use-them) Всегда используйте модули (`import`/`export`) вместо нестандартных модульных систем. Вы всегда сможете транспилировать код в вашу любимую модульную систему.\n\n    \u003e Почему? Модули — это будущее. Давайте начнём использовать будущее уже сейчас!\n\n    ```javascript\n    // плохо\n    const AirbnbStyleGuide = require('./AirbnbStyleGuide');\n    module.exports = AirbnbStyleGuide.es6;\n\n    // ok\n    import AirbnbStyleGuide from './AirbnbStyleGuide';\n    export default AirbnbStyleGuide.es6;\n\n    // отлично\n    import { es6 } from './AirbnbStyleGuide';\n    export default es6;\n    ```\n\n  \u003ca name=\"modules--no-wildcard\"\u003e\u003c/a\u003e\u003ca name=\"10.2\"\u003e\u003c/a\u003e\n  - [10.2](#modules--no-wildcard) Не используйте импорт через `*`.\n\n    \u003e Почему? Это гарантирует, что у вас есть единственный экспорт по умолчанию.\n\n    ```javascript\n    // плохо\n    import * as AirbnbStyleGuide from './AirbnbStyleGuide';\n\n    // хорошо\n    import AirbnbStyleGuide from './AirbnbStyleGuide';\n    ```\n\n  \u003ca name=\"modules--no-export-from-import\"\u003e\u003c/a\u003e\u003ca name=\"10.3\"\u003e\u003c/a\u003e\n  - [10.3](#modules--no-export-from-import) Не экспортируйте прямо из импорта.\n\n    \u003e Почему? Несмотря на то, что запись в одну строку является краткой, разделение на отдельные строки делает вещи последовательными.\n\n    ```javascript\n    // плохо\n    // файл es6.js\n    export { es6 as default } from './AirbnbStyleGuide';\n\n    // хорошо\n    // файл es6.js\n    import { es6 } from './AirbnbStyleGuide';\n    export default es6;\n    ```\n\n  \u003ca name=\"modules--no-duplicate-imports\"\u003e\u003c/a\u003e\n  - [10.4](#modules--no-duplicate-imports) Импортируйте из пути только один раз.\n eslint: [`no-duplicate-imports`](https://eslint.org/docs/rules/no-duplicate-imports)\n    \u003e Почему? Наличие нескольких строк, которые импортируют из одного и того же файла, может сделать код неподдерживаемым.\n\n    ```javascript\n    // плохо\n    import foo from 'foo';\n    // … какие-то другие импорты … //\n    import { named1, named2 } from 'foo';\n\n    // хорошо\n    import foo, { named1, named2 } from 'foo';\n\n    // хорошо\n    import foo, {\n      named1,\n      named2,\n    } from 'foo';\n    ```\n\n  \u003ca name=\"modules--no-mutable-exports\"\u003e\u003c/a\u003e\n  - [10.5](#modules--no-mutable-exports) Не экспортируйте изменяемые переменные.\n eslint: [`import/no-mutable-exports`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md)\n    \u003e Почему? Вообще, следует избегать мутации, в особенности при экспорте изменяемых переменных. Несмотря на то, что эта техника может быть необходима в редких случаях, в основном только константа должна быть экспортирована.\n\n    ```javascript\n    // плохо\n    let foo = 3;\n    export { foo };\n\n    // хорошо\n    const foo = 3;\n    export { foo };\n    ```\n\n  \u003ca name=\"modules--prefer-default-export\"\u003e\u003c/a\u003e\n  - [10.6](#modules--prefer-default-export) В модулях с единственным экспортом предпочтительнее использовать экспорт по умолчанию, а не экспорт по имени.\n eslint: [`import/prefer-default-export`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md)\n    \u003e Почему? Для того чтобы поощрять создание множества файлов, которые бы экспортировали одну сущность, т.к. это лучше для читабельности и поддержки кода.\n\n    ```javascript\n    // плохо\n    export function foo() {}\n\n    // хорошо\n    export default function foo() {}\n    ```\n\n  \u003ca name=\"modules--imports-first\"\u003e\u003c/a\u003e\n  - [10.7](#modules--imports-first) Поместите все импорты выше остальных инструкций.\n eslint: [`import/first`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md)\n    \u003e Почему? Так как `import` обладает подъёмом, то хранение их всех в начале файла предотвращает от неожиданного поведения.\n\n    ```javascript\n    // плохо\n    import foo from 'foo';\n    foo.init();\n\n    import bar from 'bar';\n\n    // хорошо\n    import foo from 'foo';\n    import bar from 'bar';\n\n    foo.init();\n    ```\n\n  \u003ca name=\"modules--multiline-imports-over-newlines\"\u003e\u003c/a\u003e\n  - [10.8](#modules--multiline-imports-over-newlines) Импорты на нескольких строках должны быть с отступами как у многострочных литералов массива и объекта. eslint: [`object-curly-newline`](https://eslint.org/docs/rules/object-curly-newline)\n\n    \u003e Почему? Фигурные скобки следуют тем же правилам отступа как и любая другая фигурная скобка блока в этом руководстве, тоже самое касается висячих запятых.\n\n    ```javascript\n    // плохо\n    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';\n\n    // хорошо\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\"\u003e\u003c/a\u003e\n  - [10.9](#modules--no-webpack-loader-syntax) Запретите синтаксис загрузчика Webpack в импорте.\n eslint: [`import/no-webpack-loader-syntax`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md)\n    \u003e Почему? Использование Webpack синтаксиса связывает код с упаковщиком модулей. Предпочтительно использовать синтаксис загрузчика в `webpack.config.js`.\n\n    ```javascript\n    // плохо\n    import fooSass from 'css!sass!foo.scss';\n    import barCss from 'style!css!bar.css';\n\n    // хорошо\n    import fooSass from 'foo.scss';\n    import barCss from 'bar.css';\n    ```\n\n  \u003ca name=\"modules--import-extensions\"\u003e\u003c/a\u003e\n  - [10.10](#modules--import-extensions) Не указывайте JavaScript расширения файлов\n eslint: [`import/extensions`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md)\n    \u003e Почему? Добавление расширений препятствует рефакторингу и нецелесообразно жёстко программируются детали реализации модуля, который вы импортируете в каждом потребителе.\n\n    ```javascript\n    // плохо\n    import foo from './foo.js';\n    import bar from './bar.jsx';\n    import baz from './baz/index.jsx';\n\n    // хорошо\n    import foo from './foo';\n    import bar from './bar';\n    import baz from './baz';\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"iterators-and-generators\"\u003eИтераторы и генераторы\u003c/a\u003e\n\n  \u003ca name=\"iterators--nope\"\u003e\u003c/a\u003e\u003ca name=\"11.1\"\u003e\u003c/a\u003e\n  - [11.1](#iterators--nope) Не используйте итераторы. Применяйте функции высшего порядка вместо таких циклов как `for-in` или `for-of`. eslint: [`no-iterator`](https://eslint.org/docs/rules/no-iterator.html) [`no-restricted-syntax`](https://eslint.org/docs/rules/no-restricted-syntax)\n\n    \u003e Почему? Это обеспечивает соблюдение нашего правила о неизменности переменных. Работать с чистыми функциями, которые возвращают значение, проще, чем с функциями с побочными эффектами.\n\n    \u003e Используйте `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / ... для итерации по массивам, а `Object.keys()` / `Object.values()` / `Object.entries()` для создания массивов, с помощью которых можно итерироваться по объектам.\n\n    ```javascript\n    const numbers = [1, 2, 3, 4, 5];\n\n    // плохо\n    let sum = 0;\n    for (let num of numbers) {\n      sum += num;\n    }\n    sum === 15;\n\n    // хорошо\n    let sum = 0;\n    numbers.forEach((num) =\u003e {\n      sum += num;\n    });\n    sum === 15;\n\n    // отлично (используйте силу функций)\n    const sum = numbers.reduce((total, num) =\u003e total + num, 0);\n    sum === 15;\n\n    // плохо\n    const increasedByOne = [];\n    for (let i = 0; i \u003c numbers.length; i++) {\n      increasedByOne.push(numbers[i] + 1);\n    }\n\n    // хорошо\n    const increasedByOne = [];\n    numbers.forEach((num) =\u003e {\n      increasedByOne.push(num + 1);\n    });\n\n    // отлично (продолжайте в том же духе)\n    const increasedByOne = numbers.map((num) =\u003e num + 1);\n    ```\n\n  \u003ca name=\"generators--nope\"\u003e\u003c/a\u003e\u003ca name=\"11.2\"\u003e\u003c/a\u003e\n  - [11.2](#generators--nope) Не используйте пока генераторы.\n\n    \u003e Почему? Они не очень хорошо транспилируются в ES5.\n\n  \u003ca name=\"generators--spacing\"\u003e\u003c/a\u003e\n  - [11.3](#generators--spacing) Если всё-таки необходимо использовать генераторы, или вы не обратили внимания на [наш совет](#generators--nope), убедитесь, что `*` у функции генератора расположена должным образом. eslint: [`generator-star-spacing`](https://eslint.org/docs/rules/generator-star-spacing)\n\n    \u003e Почему? `function` и `*` являются частью одного и того же ключевого слова. `*` не является модификатором для `function`, `function*` является уникальной конструкцией, отличной от `function`.\n\n    ```javascript\n    // плохо\n    function * foo() {\n      // ...\n    }\n\n    const bar = function * () {\n      // ...\n    };\n\n    const baz = function *() {\n      // ...\n    };\n\n    const quux = function*() {\n      // ...\n    };\n\n    function*foo() {\n      // ...\n    }\n\n    function *foo() {\n      // ...\n    }\n\n    // очень плохо\n    function\n    *\n    foo() {\n      // ...\n    }\n\n    const wat = function\n    *\n    () {\n      // ...\n    };\n\n    // хорошо\n    function* foo() {\n      // ...\n    }\n\n    const foo = function* () {\n      // ...\n    };\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"properties\"\u003eСвойства\u003c/a\u003e\n\n  \u003ca name=\"properties--dot\"\u003e\u003c/a\u003e\u003ca name=\"12.1\"\u003e\u003c/a\u003e\n  - [12.1](#properties--dot) Используйте точечную нотацию для доступа к свойствам. eslint: [`dot-notation`](https://eslint.org/docs/rules/dot-notation.html)\n\n    ```javascript\n    const luke = {\n      jedi: true,\n      age: 28,\n    };\n\n    // плохо\n    const isJedi = luke['jedi'];\n\n    // хорошо\n    const isJedi = luke.jedi;\n    ```\n\n  \u003ca name=\"properties--bracket\"\u003e\u003c/a\u003e\u003ca name=\"12.2\"\u003e\u003c/a\u003e\n  - [12.2](#properties--bracket) Используйте скобочную нотацию `[]`, когда название свойства хранится в переменной.\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\"\u003e\u003c/a\u003e\n  - [12.3](#es2016-properties--exponentiation-operator) Используйте оператор `**` для возведения в степень. eslint: [`no-restricted-properties`](https://eslint.org/docs/rules/no-restricted-properties).\n\n    ```javascript\n    // плохо\n    const binary = Math.pow(2, 10);\n\n    // хорошо\n    const binary = 2 ** 10;\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"variables\"\u003eПеременные\u003c/a\u003e\n\n  \u003ca name=\"variables--const\"\u003e\u003c/a\u003e\u003ca name=\"13.1\"\u003e\u003c/a\u003e\n  - [13.1](#variables--const) Всегда используйте `const` или `let` для объявления переменных. Невыполнение этого требования приведёт к появлению глобальных переменных. Необходимо избегать загрязнения глобального пространства имён. eslint: [`no-undef`](https://eslint.org/docs/rules/no-undef) [`prefer-const`](https://eslint.org/docs/rules/prefer-const)\n\n    ```javascript\n    // плохо\n    superPower = new SuperPower();\n\n    // хорошо\n    const superPower = new SuperPower();\n    ```\n\n  \u003ca name=\"variables--one-const\"\u003e\u003c/a\u003e\u003ca name=\"13.2\"\u003e\u003c/a\u003e\n  - [13.2](#variables--one-const) Используйте объявление `const` или `let` для каждой переменной или присвоения. eslint: [`one-var`](https://eslint.org/docs/rules/one-var.html)\n\n    \u003e Почему? Таким образом проще добавить новые переменные. Также вы никогда не будете беспокоиться о перемещении `;` и `,` и об отображении изменений в пунктуации. Вы также можете пройтись по каждому объявлению с помощью отладчика, вместо того, чтобы прыгать через все сразу.\n\n    ```javascript\n    // плохо\n    const items = getItems(),\n        goSportsTeam = true,\n        dragonball = 'z';\n\n    // плохо\n    // (сравните с кодом выше и попытайтесь найти ошибку)\n    const items = getItems(),\n        goSportsTeam = true;\n        dragonball = 'z';\n\n    // хорошо\n    const items = getItems();\n    const goSportsTeam = true;\n    const dragonball = 'z';\n    ```\n\n  \u003ca name=\"variables--const-let-group\"\u003e\u003c/a\u003e\u003ca name=\"13.3\"\u003e\u003c/a\u003e\n  - [13.3](#variables--const-let-group) В первую очередь группируйте `const`, а затем `let`.\n\n    \u003e Почему? Это полезно, когда в будущем вам понадобится создать переменную, зависимую от предыдущих.\n\n    ```javascript\n    // плохо\n    let i, len, dragonball,\n        items = getItems(),\n        goSportsTeam = true;\n\n    // плохо\n    let i;\n    const items = getItems();\n    let dragonball;\n    const goSportsTeam = true;\n    let len;\n\n    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"13.4\"\u003e\u003c/a\u003e\n  - [13.4](#variables--define-where-used) Создавайте переменные там, где они вам необходимы, но помещайте их в подходящее место.\n\n    \u003e Почему? `let` и `const` имеют блочную область видимости, а не функциональную.\n\n    ```javascript\n    // плохо - вызов ненужной функции\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    // хорошо\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\"\u003e\u003c/a\u003e\u003ca name=\"13.5\"\u003e\u003c/a\u003e\n  - [13.5](#variables--no-chain-assignment) Не создавайте цепочки присваивания переменных. eslint: [`no-multi-assign`](https://eslint.org/docs/rules/no-multi-assign)\n\n    \u003e Почему? Такие цепочки создают неявные глобальные переменные.\n\n    ```javascript\n    // плохо\n    (function example() {\n      // JavaScript интерпретирует это, как\n      // let a = ( b = ( c = 1 ) );\n      // Ключевое слово let применится только к переменной a;\n      // переменные b и c станут глобальными.\n      let a = b = c = 1;\n    }());\n\n    console.log(a); // throws ReferenceError\n    console.log(b); // 1\n    console.log(c); // 1\n\n    // хорошо\n    (function example() {\n      let a = 1;\n      let b = a;\n      let c = a;\n    }());\n\n    console.log(a); // throws ReferenceError\n    console.log(b); // throws ReferenceError\n    console.log(c); // throws ReferenceError\n\n    // тоже самое и для `const`\n    ```\n\n  \u003ca name=\"variables--unary-increment-decrement\"\u003e\u003c/a\u003e\u003ca name=\"13.6\"\u003e\u003c/a\u003e\n  - [13.6](#variables--unary-increment-decrement) Избегайте использования унарных инкрементов и декрементов (`++`, `--`). eslint [`no-plusplus`](https://eslint.org/docs/rules/no-plusplus)\n\n    \u003e Почему? Согласно документации eslint, унарные инкремент и декремент автоматически вставляют точку с запятой, что может стать причиной трудноуловимых ошибок при инкрементировании и декрементировании значений. Также нагляднее изменять ваши значения таким образом `num += 1` вместо `num++` или `num ++`. Запрет на унарные инкремент и декремент ограждает вас от непреднамеренных преждевременных инкрементаций/декрементаций значений, которые могут привести к непредсказуемому поведению вашей программы.\n\n    ```javascript\n    // плохо\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    // хорошо\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) =\u003e a + b, 0);\n    const truthyCount = array.filter(Boolean).length;\n    ```\n\n  \u003ca name=\"variables--linebreak\"\u003e\u003c/a\u003e\n  - [13.7](#variables--linebreak) В присвоении избегайте разрывов строк до и после `=`. Если ваше присвоение нарушает правило [`max-len`](https://eslint.org/docs/rules/max-len.html), оберните значение в круглые скобки. eslint [`operator-linebreak`](https://eslint.org/docs/rules/operator-linebreak.html).\n\n    \u003e Почему? Разрывы строк до и после `=` могут приводить к путанице в понимании значения.\n\n    ```javascript\n    // плохо\n    const foo =\n      superLongLongLongLongLongLongLongLongFunctionName();\n\n    // плохо\n    const foo\n      = 'superLongLongLongLongLongLongLongLongString';\n\n    // хорошо\n    const foo = (\n      superLongLongLongLongLongLongLongLongFunctionName()\n    );\n\n    // хорошо\n    const foo = 'superLongLongLongLongLongLongLongLongString';\n    ```\n\n  \u003ca name=\"variables--no-unused-vars\"\u003e\u003c/a\u003e\n  - [13.8](#variables--no-unused-vars) Запретить неиспользуемые переменные. eslint: [`no-unused-vars`](https://eslint.org/docs/rules/no-unused-vars)\n\n    \u003e Почему? Переменные, которые объявлены и не используются в коде, скорее всего, являются ошибкой из-за незавершённого рефакторинга. Такие переменные занимают место в коде и могут привести к путанице при чтении.\n\n    ```javascript\n    // плохо\n\n    var some_unused_var = 42;\n\n    // Переменные, которые используются только для записи, не считаются используемыми.\n    var y = 10;\n    y = 5;\n\n    // Чтение для собственной модификации.\n    var z = 0;\n    z = z + 1;\n\n    // Неиспользуемые аргументы функции.\n    function getX(x, y) {\n        return x;\n    }\n\n    // хорошо\n\n    function getXPlusY(x, y) {\n      return x + y;\n    }\n\n    var x = 1;\n    var y = a + 2;\n\n    alert(getXPlusY(x, y));\n\n    // Переменная 'type' игнорируется, даже если она не испольуется, потому что рядом есть rest-свойство.\n    // Эта форма извлечения объекта, которая опускает указанные ключи.\n    var { type, ...coords } = data;\n    // 'coords' теперь 'data' объект без свойства 'type'.\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"hoisting\"\u003eПодъём\u003c/a\u003e\n\n  \u003ca name=\"hoisting--about\"\u003e\u003c/a\u003e\u003ca name=\"14.1\"\u003e\u003c/a\u003e\n  - [14.1](#hoisting--about) Объявления `var` поднимаются в начало области видимости ближайшей закрывающей их функции, а их присвоение нет. Объявления `const` и `let` работают по новой концепции называемой [Временные Мёртвые Зоны (Temporal Dead Zone)](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/let#временные_мёртвые_зоны_и_ошибки_при_использовании_let). Важно знать, почему использовать [typeof больше не безопасно](https://web.archive.org/web/20200121061528/http://es-discourse.com/t/why-typeof-is-no-longer-safe/15).\n\n    ```javascript\n    // мы знаем, что это не будет работать\n    // (если нет глобальной переменной notDefined)\n    function example() {\n      console.log(notDefined); // =\u003e выбросит ошибку ReferenceError\n    }\n\n    // обращение к переменной до её создания\n    // будет работать из-за подъёма.\n    // Примечание: значение true не поднимается.\n    function example() {\n      console.log(declaredButNotAssigned); // =\u003e undefined\n      var declaredButNotAssigned = true;\n    }\n\n    // интерпретатор понимает объявление\n    // переменной в начало области видимости.\n    // это означает, что наш пример\n    // можно переписать таким образом:\n    function example() {\n      let declaredButNotAssigned;\n      console.log(declaredButNotAssigned); // =\u003e undefined\n      declaredButNotAssigned = true;\n    }\n\n    // использование const и let\n    function example() {\n      console.log(declaredButNotAssigned); // =\u003e выбросит ошибку ReferenceError\n      console.log(typeof declaredButNotAssigned); // =\u003e выбросит ошибку ReferenceError\n      const declaredButNotAssigned = true;\n    }\n    ```\n\n  \u003ca name=\"hoisting--anon-expressions\"\u003e\u003c/a\u003e\u003ca name=\"14.2\"\u003e\u003c/a\u003e\n  - [14.2](#hoisting--anon-expressions) Для анонимных функциональных выражений наверх области видимости поднимается название переменной, но не её значение.\n\n    ```javascript\n    function example() {\n      console.log(anonymous); // =\u003e undefined\n\n      anonymous(); // =\u003e TypeError anonymous не является функцией\n\n      var anonymous = function () {\n        console.log('anonymous function expression');\n      };\n    }\n    ```\n\n  \u003ca name=\"hoisting--named-expressions\"\u003e\u003c/a\u003e\u003ca name=\"hoisting--named-expressions\"\u003e\u003c/a\u003e\u003ca name=\"14.3\"\u003e\u003c/a\u003e\n  - [14.3](#hoisting--named-expressions) Для именованных функциональных выражений наверх области видимости поднимается название переменной, но не имя или тело функции.\n\n    ```javascript\n    function example() {\n      console.log(named); // =\u003e undefined\n\n      named(); // =\u003e TypeError named не является функцией\n\n      superPower(); // =\u003e ReferenceError superPower не определена\n\n      var named = function superPower() {\n        console.log('Flying');\n      };\n    }\n\n    // тоже самое справедливо, когда имя функции\n    // совпадает с именем переменной.\n    function example() {\n      console.log(named); // =\u003e undefined\n\n      named(); // =\u003e TypeError named не является функцией\n\n      var named = function named() {\n        console.log('named');\n      };\n    }\n    ```\n\n  \u003ca name=\"hoisting--declarations\"\u003e\u003c/a\u003e\u003ca name=\"14.4\"\u003e\u003c/a\u003e\n  - [14.4](#hoisting--declarations) При объявлении функции её имя и тело поднимаются наверх области видимости.\n\n    ```javascript\n    function example() {\n      superPower(); // =\u003e Flying\n\n      function superPower() {\n        console.log('Flying');\n      }\n    }\n    ```\n\n  - Более подробно можно прочитать в статье [JavaScript Scoping \u0026 Hoisting](https://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/) от [Ben Cherry](https://www.adequatelygood.com/).\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"comparison-operators--equality\"\u003eОператоры сравнения и равенства\u003c/a\u003e\n\n  \u003ca name=\"comparison--eqeqeq\"\u003e\u003c/a\u003e\u003ca name=\"15.1\"\u003e\u003c/a\u003e\n  - [15.1](#comparison--eqeqeq) Используйте `===` и `!==` вместо `==` и `!=`. eslint: [`eqeqeq`](https://eslint.org/docs/rules/eqeqeq.html)\n\n  \u003ca name=\"comparison--if\"\u003e\u003c/a\u003e\u003ca name=\"15.2\"\u003e\u003c/a\u003e\n  - [15.2](#comparison--if) Условные операторы, такие как `if`, вычисляются путём приведения к логическому типу `Boolean` через абстрактный метод `ToBoolean` и всегда следуют следующим правилам:\n    - **Object** соответствует **true**\n    - **Undefined** соответствует **false**\n    - **Null** соответствует **false**\n    - **Boolean** соответствует **значению булева типа**\n    - **Number** соответствует **false**, если **+0, -0, or NaN**, в остальных случаях **true**\n    - **String** соответствует **false**, если строка пустая `''`, в остальных случаях **true**\n\n    ```javascript\n    if ([0] \u0026\u0026 []) {\n      // true\n      // Массив (даже пустой) является объектом, а объекты возвращают true\n    }\n    ```\n\n  \u003ca name=\"comparison--shortcuts\"\u003e\u003c/a\u003e\u003ca name=\"15.3\"\u003e\u003c/a\u003e\n  - [15.3](#comparison--shortcuts) Используйте сокращения для булевских типов, а для строк и чисел применяйте явное сравнение.\n\n    ```javascript\n    // плохо\n    if (isValid === true) {\n      // ...\n    }\n\n    // хорошо\n    if (isValid) {\n      // ...\n    }\n\n    // плохо\n    if (name) {\n      // ...\n    }\n\n    // хорошо\n    if (name !== '') {\n      // ...\n    }\n\n    // плохо\n    if (collection.length) {\n      // ...\n    }\n\n    // хорошо\n    if (collection.length \u003e 0) {\n      // ...\n    }\n    ```\n\n  \u003ca name=\"comparison--moreinfo\"\u003e\u003c/a\u003e\u003ca name=\"15.4\"\u003e\u003c/a\u003e\n  - [15.4](#comparison--moreinfo) Более подробную информацию можно узнать в статье [Truth Equality and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) от Angus Croll.\n\n  \u003ca name=\"comparison--switch-blocks\"\u003e\u003c/a\u003e\u003ca name=\"15.5\"\u003e\u003c/a\u003e\n  - [15.5](#comparison--switch-blocks) Используйте фигурные скобки для `case` и `default`, если они содержат лексические декларации (например, `let`, `const`, `function`, и `class`). eslint: [`no-case-declarations`](https://eslint.org/docs/rules/no-case-declarations.html).\n\n    \u003e Почему? Лексические декларации видны во всем `switch` блоке, но инициализируются только при присваивании, которое происходит при входе в блок `case`. Возникают проблемы, когда множество `case` пытаются определить одно и то же.\n\n    ```javascript\n    // плохо\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          // ...\n        }\n        break;\n      default:\n        class C {}\n    }\n\n    // хорошо\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          // ...\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\"\u003e\u003c/a\u003e\u003ca name=\"15.6\"\u003e\u003c/a\u003e\n  - [15.6](#comparison--nested-ternaries) Тернарные операторы не должны быть вложены и в большинстве случаев должны быть расположены на одной строке. eslint: [`no-nested-ternary`](https://eslint.org/docs/rules/no-nested-ternary.html).\n\n    ```javascript\n    // плохо\n    const foo = maybe1 \u003e maybe2\n      ? \"bar\"\n      : value1 \u003e value2 ? \"baz\" : null;\n\n    // разбит на два отдельных тернарных выражения\n    const maybeNull = value1 \u003e value2 ? 'baz' : null;\n\n    const foo = maybe1 \u003e maybe2\n      ? 'bar'\n      : maybeNull;\n\n    // отлично\n    const foo = maybe1 \u003e maybe2 ? 'bar' : maybeNull;\n    ```\n\n  \u003ca name=\"comparison--unneeded-ternary\"\u003e\u003c/a\u003e\u003ca name=\"15.7\"\u003e\u003c/a\u003e\n  - [15.7](#comparison--unneeded-ternary) Избегайте ненужных тернарных операторов. eslint: [`no-unneeded-ternary`](https://eslint.org/docs/rules/no-unneeded-ternary.html).\n\n    ```javascript\n    // плохо\n    const foo = a ? a : b;\n    const bar = c ? true : false;\n    const baz = c ? false : true;\n\n    // хорошо\n    const foo = a || b;\n    const bar = !!c;\n    const baz = !c;\n    ```\n\n  \u003ca name=\"comparison--no-mixed-operators\"\u003e\u003c/a\u003e\n  - [15.8](#comparison--no-mixed-operators) При смешивании операторов, помещайте их в круглые скобки. Единственным исключением являются стандартные арифметические операторы: `+`, `-` и `**`, так как их приоритет широко известен. Мы рекомендуем заключить `/` и `*` в круглые скобки, поскольку их приоритет может быть неоднозначным, когда они смешиваются. eslint: [`no-mixed-operators`](https://eslint.org/docs/rules/no-mixed-operators.html)\n\n    \u003e Почему? Это улучшает читаемость и уточняет намерения разработчика.\n\n    ```javascript\n    // плохо\n    const foo = a \u0026\u0026 b \u003c 0 || c \u003e 0 || d + 1 === 0;\n\n    // плохо\n    const bar = a ** b - 5 % d;\n\n    // плохо\n    // можно ошибиться, думая что это (a || b) \u0026\u0026 c\n    if (a || b \u0026\u0026 c) {\n      return d;\n    }\n\n    // плохо\n    const bar = a + b / c * d;\n\n    // хорошо\n    const foo = (a \u0026\u0026 b \u003c 0) || c \u003e 0 || (d + 1 === 0);\n\n    // хорошо\n    const bar = a ** b - (5 % d);\n\n    // хорошо\n    if (a || (b \u0026\u0026 c)) {\n      return d;\n    }\n\n    // хорошо\n    const bar = a + (b / c) * d;\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"blocks\"\u003eБлоки\u003c/a\u003e\n\n  \u003ca name=\"blocks--braces\"\u003e\u003c/a\u003e\u003ca name=\"16.1\"\u003e\u003c/a\u003e\n  - [16.1](#blocks--braces) Используйте фигурные скобки, когда блок кода занимает несколько строк. eslint: [`nonblock-statement-body-position`](https://eslint.org/docs/rules/nonblock-statement-body-position)\n\n    ```javascript\n    // плохо\n    if (test)\n      return false;\n\n    // хорошо\n    if (test) return false;\n\n    // хорошо\n    if (test) {\n      return false;\n    }\n\n    // плохо\n    function foo() { return false; }\n\n    // хорошо\n    function bar() {\n      return false;\n    }\n    ```\n\n  \u003ca name=\"blocks--cuddled-elses\"\u003e\u003c/a\u003e\u003ca name=\"16.2\"\u003e\u003c/a\u003e\n  - [16.2](#blocks--cuddled-elses) Если блоки кода в условии `if` и `else` занимают несколько строк, расположите оператор `else` на той же строчке, где находится закрывающая фигурная скобка блока `if`. eslint: [`brace-style`](https://eslint.org/docs/rules/brace-style.html)\n\n    ```javascript\n    // плохо\n    if (test) {\n      thing1();\n      thing2();\n    }\n    else {\n      thing3();\n    }\n\n    // хорошо\n    if (test) {\n      thing1();\n      thing2();\n    } else {\n      thing3();\n    }\n    ```\n\n  \u003ca name=\"blocks--no-else-return\"\u003e\u003c/a\u003e\u003ca name=\"16.3\"\u003e\u003c/a\u003e\n  - [16.3](#blocks--no-else-return) Если в блоке `if` всегда выполняется оператор `return`, последующий блок `else` не нужен. `return`  внутри блока `else if`, следующем за блоком `if`, который содержит `return`, может быть разделён на несколько блоков `if`. eslint: [`no-else-return`](https://eslint.org/docs/rules/no-else-return)\n\n    ```javascript\n    // плохо\n    function foo() {\n      if (x) {\n        return x;\n      } else {\n        return y;\n      }\n    }\n\n    // плохо\n    function cats() {\n      if (x) {\n        return x;\n      } else if (y) {\n        return y;\n      }\n    }\n\n    // плохо\n    function dogs() {\n      if (x) {\n        return x;\n      } else {\n        if (y) {\n          return y;\n        }\n      }\n    }\n\n    // хорошо\n    function foo() {\n      if (x) {\n        return x;\n      }\n\n      return y;\n    }\n\n    // хорошо\n    function cats() {\n      if (x) {\n        return x;\n      }\n\n      if (y) {\n        return y;\n      }\n    }\n\n    // хорошо\n    function dogs(x) {\n      if (x) {\n        if (z) {\n          return y;\n        }\n      } else {\n        return z;\n      }\n    }\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"control-statements\"\u003eУправляющие операторы\u003c/a\u003e\n\n  \u003ca name=\"control-statements\"\u003e\u003c/a\u003e\n  - [17.1](#control-statements) Если ваш управляющий оператор (`if`, `while` и т.д.) слишком длинный или превышает максимальную длину строки, то каждое (сгруппированное) условие можно поместить на новую строку. Логический оператор должен располагаться в начале строки.\n\n    \u003e Почему? Наличие операторов в начале строки приводит к выравниванию операторов и напоминает цепочку методов. Это также улучшает читаемость, упрощая визуальное отслеживание сложной логики.\n\n    ```javascript\n    // плохо\n    if ((foo === 123 || bar === 'abc') \u0026\u0026 doesItLookGoodWhenItBecomesThatLong() \u0026\u0026 isThisReallyHappening()) {\n      thing1();\n    }\n\n    // плохо\n    if (foo === 123 \u0026\u0026\n      bar === 'abc') {\n      thing1();\n    }\n\n    // плохо\n    if (foo === 123\n      \u0026\u0026 bar === 'abc') {\n      thing1();\n    }\n\n    // плохо\n    if (\n      foo === 123 \u0026\u0026\n      bar === 'abc'\n    ) {\n      thing1();\n    }\n\n    // хорошо\n    if (\n      foo === 123\n      \u0026\u0026 bar === 'abc'\n    ) {\n      thing1();\n    }\n\n    // хорошо\n    if (\n      (foo === 123 || bar === 'abc')\n      \u0026\u0026 doesItLookGoodWhenItBecomesThatLong()\n      \u0026\u0026 isThisReallyHappening()\n    ) {\n      thing1();\n    }\n\n    // хорошо\n    if (foo === 123 \u0026\u0026 bar === 'abc') {\n      thing1();\n    }\n    ```\n\n  \u003ca name=\"control-statement--value-selection\"\u003e\u003c/a\u003e\u003ca name=\"control-statements--value-selection\"\u003e\u003c/a\u003e\n  - [17.2](#control-statements--value-selection) Не используйте операторы выбора вместо управляющих операторов.\n\n    ```javascript\n    // плохо\n    !isRunning \u0026\u0026 startRunning();\n\n    // хорошо\n    if (!isRunning) {\n      startRunning();\n    }\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"comments\"\u003eКомментарии\u003c/a\u003e\n\n  \u003ca name=\"comments--multiline\"\u003e\u003c/a\u003e\u003ca name=\"17.1\"\u003e\u003c/a\u003e\n  - [18.1](#comments--multiline) Используйте конструкцию `/** ... */` для многострочных комментариев.\n\n    ```javascript\n    // плохо\n    // make() возвращает новый элемент\n    // соответствующий переданному названию тега\n    //\n    // @param {String} tag\n    // @return {Element} element\n    function make(tag) {\n\n      // ...\n\n      return element;\n    }\n\n    // хорошо\n    /**\n     * make() возвращает новый элемент\n     * соответствующий переданному названию тега\n     */\n    function make(tag) {\n\n      // ...\n\n      return element;\n    }\n    ```\n\n  \u003ca name=\"comments--singleline\"\u003e\u003c/a\u003e\u003ca name=\"17.2\"\u003e\u003c/a\u003e\n  - [18.2](#comments--singleline) Используйте двойной слеш `//` для однострочных комментариев. Располагайте такие комментарии отдельной строкой над кодом, который хотите пояснить. Если комментарий не является первой строкой блока, добавьте сверху пустую строку.\n\n    ```javascript\n    // плохо\n    const active = true;  // это текущая вкладка\n\n    // хорошо\n    // это текущая вкладка\n    const active = true;\n\n    // плохо\n    function getType() {\n      console.log('fetching type...');\n      // установить по умолчанию тип 'no type'\n      const type = this.type || 'no type';\n\n      return type;\n    }\n\n    // хорошо\n    function getType() {\n      console.log('fetching type...');\n\n      // установить по умолчанию тип 'no type'\n      const type = this.type || 'no type';\n\n      return type;\n    }\n\n    // тоже хорошо\n    function getType() {\n      // установить по умолчанию тип 'no type'\n      const type = this.type || 'no type';\n\n      return type;\n    }\n    ```\n\n  \u003ca name=\"comments--spaces\"\u003e\u003c/a\u003e\n  - [18.3](#comments--spaces) Начинайте все комментарии с пробела, так их проще читать. eslint: [`spaced-comment`](https://eslint.org/docs/rules/spaced-comment)\n\n    ```javascript\n    // плохо\n    //это текущая вкладка\n    const active = true;\n\n    // хорошо\n    // это текущая вкладка\n    const active = true;\n\n    // плохо\n    /**\n     *make() возвращает новый элемент\n     *соответствующий переданному названию тега\n     */\n    function make(tag) {\n\n      // ...\n\n      return element;\n    }\n\n    // хорошо\n    /**\n     * make() возвращает новый элемент\n     * соответствующий переданному названию тега\n     */\n    function make(tag) {\n\n      // ...\n\n      return element;\n    }\n    ```\n\n  \u003ca name=\"comments--actionitems\"\u003e\u003c/a\u003e\u003ca name=\"17.3\"\u003e\u003c/a\u003e\n  - [18.4](#comments--actionitems) Если комментарий начинается со слов `FIXME` или `TODO`, то это помогает другим разработчикам быстро понять, когда вы хотите указать на проблему, которую надо решить, или когда вы предлагаете решение проблемы, которое надо реализовать. Такие комментарии, в отличие от обычных, побуждают к действию: `FIXME: -- нужно разобраться с этим` или `TODO: -- нужно реализовать`.\n\n  \u003ca name=\"comments--fixme\"\u003e\u003c/a\u003e\u003ca name=\"17.4\"\u003e\u003c/a\u003e\n  - [18.5](#comments--fixme) Используйте `// FIXME:`, чтобы описать проблему.\n\n    ```javascript\n    class Calculator extends Abacus {\n      constructor() {\n        super();\n\n        // FIXME: здесь не должна использоваться глобальная переменная\n        total = 0;\n      }\n    }\n    ```\n\n  \u003ca name=\"comments--todo\"\u003e\u003c/a\u003e\u003ca name=\"17.5\"\u003e\u003c/a\u003e\n  - [18.6](#comments--todo) Используйте `// TODO:`, чтобы описать решение проблемы.\n\n    ```javascript\n    class Calculator extends Abacus {\n      constructor() {\n        super();\n\n        // TODO: нужна возможность задать total через параметры\n        this.total = 0;\n      }\n    }\n    ```\n\n**[⬆ к оглавлению](#Оглавление)**\n\n## \u003ca name=\"whitespace\"\u003eПробелы\u003c/a\u003e\n\n  \u003ca name=\"whitespace--spaces\"\u003e\u003c/a\u003e\u003ca name=\"18.1\"\u003e\u003c/a\u003e\n  - [19.1](#whitespace--spaces) Используйте мягкую табуляцию (символ пробела) шириной в 2 пробела. eslint: [`indent`](https://eslint.org/docs/rules/indent.html)\n\n    ```javascript\n    // плохо\n    function foo() {\n    ∙∙∙∙let name;\n    }\n\n    // плохо\n    function bar() {\n    ∙let name;\n    }\n\n    // хорошо\n    function baz() {\n    ∙∙let name;\n    }\n    ```\n\n  \u003ca name=\"whitespace--before-blocks\"\u003e\u003c/a\u003e\u003ca name=\"18.2\"\u003e\u003c/a\u003e\n  - [19.2](#whitespace--before-blocks) Ставьте 1 пробел перед открывающей фигурной скобкой у блока. eslint: [`space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks.html)\n\n    ```javascript\n    // плохо\n    function test(){\n      console.log('test');\n    }\n\n    // хорошо\n    function test() {\n      console.log('test');\n    }\n\n    // плохо\n    dog.set('attr',{\n      age: '1 year',\n      breed: 'Bernese Mountain Dog',\n    });\n\n    // хорошо\n    dog.set('attr', {\n      age: '1 year',\n      breed: 'Bernese Mountain Dog',\n    });\n    ```\n\n  \u003ca name=\"whitespace--around-keywords\"\u003e\u003c/a\u003e\u003ca name=\"18.3\"\u003e\u003c/a\u003e\n  - [19.3](#whitespace--around-keywords) Ставьте 1 пробел перед открывающей круглой скобкой в операторах управления (`if`, `while` и т.п.). Не оставляйте пробелов между списком аргументов и названием в объявлениях и вызовах функций. eslint: [`keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing.html)\n\n    ```javascript\n    // плохо\n    if(isJedi) {\n      fight ();\n    }\n\n    // хорошо\n    if (isJedi) {\n      fight();\n    }\n\n    // плохо\n    function fight () {\n      console.log ('Swooosh!');\n    }\n\n    // хорошо\n    function fight() {\n      console.log('Swooosh!');\n    }\n    ```\n\n  \u003ca name=\"whitespace--infix-ops\"\u003e\u003c/a\u003e\u003ca name=\"18.4\"\u003e\u003c/a\u003e\n  - [19.4](#whitespace--infix-ops) Разделяйте операторы пробелами. eslint: [`space-infix-ops`](https://eslint.org/docs/rules/space-infix-ops.html)\n\n    ```javascript\n    // плохо\n    const x=y+5;\n\n    // хорошо\n    const x = y + 5;\n    ```\n\n  \u003ca name=\"whitespace--newline-at-end\"\u003e\u003c/a\u003e\u003ca name=\"18.5\"\u003e\u003c/a\u003e\n  - [19.5](#whitespace--newline-at-end) В конце файла оставляйте одну пустую строку. eslint: [`eol-last`](https://github.com/eslint/eslint/blob/master/docs/rules/eol-last.md)\n\n    ```javascript\n    // плохо\n    import { es6 } from './AirbnbStyleGuide';\n      // ...\n    export default es6;\n    ```\n\n    ```javascript\n    // плохо\n    import { es6 } from './AirbnbStyleGuide';\n      // ...\n    export default es6;↵\n    ↵\n    ```\n\n    ```javascript\n    // хорошо\n    import { es6 } from './AirbnbStyleGuide';\n      // ...\n    export default es6;↵\n    ```\n\n  \u003ca name=\"whitespace--chains\"\u003e\u003c/a\u003e\u003ca name=\"18.6\"\u003e\u003c/a\u003e\n  - [19.6](#whitespace--chains) Используйте переносы строк и отступы, когда делаете длинные цепочки методов (больше 2 методов). Ставьте точку в начале строки, чтобы дать понять, что это не новая инструкция, а продолжение цепочки. eslint: [`newline-per-chained-call`](https://eslint.org/docs/rules/newline-per-chained-call) [`no-whitespace-before-property`](https://eslint.org/docs/rules/no-whitespace-before-property)\n\n    ```javascript\n    // плохо\n    $('#items').find('.selected').highlight().end().find('.open').updateCount();\n\n    // плохо\n    $('#items').\n      find('.selected').\n        highlight().\n        end().\n      find('.open').\n        updateCount();\n\n    // хорошо\n    $('#items')\n      .find('.selected')\n        .highlight()\n        .end()\n      .find('.open')\n        .updateCount();\n\n    // плохо\n    const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)\n        .attr('width', (radius + margin) * 2).append('svg:g')\n        .attr('transform', `translate(${radius + margin},${radius + margin})`)\n        .call(tron.led);\n\n    // хорошо\n    const leds = stage.selectAll('.led')\n        .data(data)\n      .enter().append('svg:svg')\n        .classed('led', true)\n        .attr('width', (radius + margin) * 2)\n      .append('svg:g')\n        .attr('transform', `translate(${radius + margin},${radius + margin})`)\n        .call(tron.led);\n\n    // хорошо\n    const leds = stage.selectAll('.led').data(data);\n    const svg = leds.enter().append('svg:svg');\n    svg.classed('led', true).attr('width', (radius + margin) * 2);\n    const g = svg.append('svg:g');\n    g.attr('transform', `translate(${radius + margin},${radius + margin})`).call(tron.led);\n    ```\n\n  \u003ca name=\"whitespace--after-blocks\"\u003e\u003c/a\u003e\u003ca name=\"18.7\"\u003e\u003c/a\u003e\n  - [19.7](#whitespace--after-blocks) Оставляйте пустую строку между блоком кода и следующей инструкцией.\n\n    ```javascript\n    // плохо\n    if (foo) {\n      return bar;\n    }\n    return baz;\n\n    // хорошо\n    if (foo) {\n      return bar;\n    }\n\n    return baz;\n\n    // плохо\n    const obj = {\n      foo() {\n      },\n      bar() {\n      },\n    };\n    return obj;\n\n    // хорошо\n    const obj = {\n      foo() {\n      },\n\n      bar() {\n      },\n    };\n\n    return obj;\n\n    // плохо\n    const arr = [\n      function foo() {\n      },\n      function bar() {\n      },\n    ];\n    return arr;\n\n    // хорошо\n    const ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonidlebedev%2Fjavascript-airbnb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleonidlebedev%2Fjavascript-airbnb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonidlebedev%2Fjavascript-airbnb/lists"}