javascript - ジャバスクリプトスタイルガイド

(JavaScript Style Guide)

Created at: 2012-11-02 07:13:50
Language: JavaScript
License: MIT

Airbnb JavaScript Style Guide() {

JavaScriptへのほとんど合理的なアプローチ

:このガイドでは、Babelを使用していることを前提としており、babel-preset-airbnbまたは同等のものを使用する必要があります。また、アプリに shims/polyfill を airbnb-browser-shim または同等のものと共にインストールしていることも前提としています。

ダウンロード ダウンロード ギッター

このガイドは他の言語でも入手できます。翻訳を見る

その他のスタイルガイド

目次

  1. 種類
  2. 参照
  3. オブジェクト
  4. 配列
  5. デストラクチャリング
  6. ストリングス
  7. 関数
  8. 矢印関数
  9. クラスとコンストラクタ
  10. モジュール
  11. イテレータとジェネレータ
  12. プロパティ
  13. 変数
  14. 巻き上げ
  15. 比較演算子と等価
  16. ブロック
  17. 制御ステートメント
  18. コメント
  19. 空白
  20. コンマ
  21. セミコロン
  22. 型キャスト&強制型変換
  23. 命名規則
  24. アクセサー
  25. イベント
  26. jQuery
  27. ECMAスクリプト 5 の互換性
  28. ECMAScript 6+ (ES 2015+) スタイル
  29. 標準ライブラリ
  30. テスティング
  31. パフォーマンス
  32. リソース
  33. 野生で
  34. 翻訳
  35. JavaScript スタイルガイドガイド
  36. JavaScriptについてチャットしてください
  37. 貢献
  38. ライセンス
  39. 改正

種類

  • 1.1 プリミティブ: プリミティブ型にアクセスするときは、その値を直接操作します。

    • string
    • number
    • boolean
    • null
    • undefined
    • symbol
    • bigint

    const foo = 1;
    let bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
    • シンボルと BigInt は忠実にポリフィルできないため、ネイティブにサポートされていないブラウザー/環境をターゲットにする場合は使用しないでください。

  • 1.2 複合型: 複合型にアクセスするときは、その値への参照を処理します。

    • object
    • array
    • function

    const foo = [1, 2];
    const bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

一番上に戻る

参照

  • 2.1すべての参照に使用します。の使用は避けてください。ESLINT: 優先定数非構成割り当て

    const
    var

    なぜでしょうか。これにより、参照を再割り当てできなくなり、バグが発生したり、コードを理解しにくくなったりする可能性があります。

    // bad
    var a = 1;
    var b = 2;
    
    // good
    const a = 1;
    const b = 2;

  • 2.2 参照を再割り当てする必要がある場合は、 の代わりに を使用します。エスリント: 変数なし

    let
    var

    なぜでしょうか。 は、 のように関数スコープではなくブロックスコープです。

    let
    var

    // bad
    var count = 1;
    if (true) {
      count += 1;
    }
    
    // good, use the let.
    let count = 1;
    if (true) {
      count += 1;
    }

  • 2.3 と はどちらもブロックスコープであるのに対し、 は関数スコープであることに注意してください。

    let
    const
    var

    // const and let only exist in the blocks they are defined in.
    {
      let a = 1;
      const b = 1;
      var c = 1;
    }
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError
    console.log(c); // Prints 1

    上記のコードでは、その参照を見ることができ、番号が含まれている間、ReferenceErrorを生成します。これは、 とがブロックスコープであり、 が包含関数にスコープされているためです。

    a
    b
    c
    a
    b
    c

一番上に戻る

オブジェクト

  • 3.2 動的プロパティ名を持つオブジェクトを作成する場合は、計算プロパティ名を使用します。

    なぜでしょうか。これにより、オブジェクトのすべてのプロパティを1か所で定義できます。

    function getKey(k) {
      return `a key named ${k}`;
    }
    
    // bad
    const obj = {
      id: 5,
      name: 'San Francisco',
    };
    obj[getKey('enabled')] = true;
    
    // good
    const obj = {
      id: 5,
      name: 'San Francisco',
      [getKey('enabled')]: true,
    };

  • 3.3オブジェクトメソッドの省略形を使用します。ESLINT: オブジェクト-省略形

    // bad
    const atom = {
      value: 1,
    
      addValue: function (value) {
        return atom.value + value;
      },
    };
    
    // good
    const atom = {
      value: 1,
    
      addValue(value) {
        return atom.value + value;
      },
    };

  • 3.4 プロパティ値の省略形を使用します。ESLINT: オブジェクト-省略形

    なぜでしょうか。それは短くて説明的です。

    const lukeSkywalker = 'Luke Skywalker';
    
    // bad
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
    };

  • 3.5 オブジェクト宣言の先頭で短縮形プロパティをグループ化します。

    なぜでしょうか。どのプロパティが短縮形を使用しているかを簡単に判断できます。

    const anakinSkywalker = 'Anakin Skywalker';
    const lukeSkywalker = 'Luke Skywalker';
    
    // bad
    const obj = {
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      lukeSkywalker,
      episodeThree: 3,
      mayTheFourth: 4,
      anakinSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
      anakinSkywalker,
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      episodeThree: 3,
      mayTheFourth: 4,
    };

  • 3.6 無効な識別子であるプロパティのみを引用符で囲みます。エスリント:引用小道具

    なぜでしょうか。一般的に、主観的に読みやすいと考えています。構文の強調表示が改善され、多くのJSエンジンによってより簡単に最適化されます。

    // bad
    const bad = {
      'foo': 3,
      'bar': 4,
      'data-blah': 5,
    };
    
    // good
    const good = {
      foo: 3,
      bar: 4,
      'data-blah': 5,
    };

  • 3.7 、などのメソッドを直接呼び出さないESLINT:プロトタイプビルトインなし

    Object.prototype
    hasOwnProperty
    propertyIsEnumerable
    isPrototypeOf

    なぜでしょうか。これらのメソッドは、問題のオブジェクトのプロパティによってシャドウされている可能性があります-考慮してください-または、オブジェクトはnullオブジェクト()である可能性があります。

    { hasOwnProperty: false }
    Object.create(null)

    // bad
    console.log(object.hasOwnProperty(key));
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // best
    const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
    console.log(has.call(object, key));
    /* or */
    import has from 'has'; // https://www.npmjs.com/package/has
    console.log(has(object, key));
    /* or */
    console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown

  • 3.8 Object.ssignよりもオブジェクトスプレッド構文を優先して、浅いコピーオブジェクトにします。object rest パラメーター構文を使用して、特定のプロパティが省略された新しいオブジェクトを取得します。エスリント:優先オブジェクトスプレッド

    // very bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ
    delete copy.a; // so does this
    
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
    
    // good
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    
    const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

一番上に戻る

配列

  • 4.2 配列に項目を追加するには、直接代入の代わりに Array#push を使用します。

    const someStack = [];
    
    // bad
    someStack[someStack.length] = 'abracadabra';
    
    // good
    someStack.push('abracadabra');

  • 4.3 配列スプレッドを使用して配列をコピーする。

    ...

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i += 1) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];

  • 4.4 反復可能なオブジェクトを配列に変換するには、Array.from の代わりにスプレッドを使用します。

    ...

    const foo = document.querySelectorAll('.foo');
    
    // good
    const nodes = Array.from(foo);
    
    // best
    const nodes = [...foo];

  • 4.5 配列のようなオブジェクトを配列に変換するには、Array.from を使用します。

    const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
    
    // bad
    const arr = Array.prototype.slice.call(arrLike);
    
    // good
    const arr = Array.from(arrLike);

  • 4.6 イテラブルへのマッピングにはスプレッドの代わりに Array.from を使用すると、中間配列の作成が回避されるためです。

    ...

    // bad
    const baz = [...foo].map(bar);
    
    // good
    const baz = Array.from(foo, bar);

  • 4.7 配列メソッドのコールバックで return ステートメントを使用します。関数本体が副作用のない式を返す単一のステートメントで構成されている場合は、8.2以降、戻り値を省略してもかまいません。ESLint: 配列コールバックリターン

    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => x + 1);
    
    // bad - no returned value means `acc` becomes undefined after the first iteration
    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
      const flatten = acc.concat(item);
    });
    
    // good
    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
      const flatten = acc.concat(item);
      return flatten;
    });
    
    // bad
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      } else {
        return false;
      }
    });
    
    // good
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      }
    
      return false;
    });

  • 4.8配列に複数の行がある場合、配列の括弧を開いた後と閉じる前に改行を使用する

    // bad
    const arr = [
      [0, 1], [2, 3], [4, 5],
    ];
    
    const objectInArray = [{
      id: 1,
    }, {
      id: 2,
    }];
    
    const numberInArray = [
      1, 2,
    ];
    
    // good
    const arr = [[0, 1], [2, 3], [4, 5]];
    
    const objectInArray = [
      {
        id: 1,
      },
      {
        id: 2,
      },
    ];
    
    const numberInArray = [
      1,
      2,
    ];

一番上に戻る

デストラクチャリング

  • 5.1 オブジェクトの複数のプロパティにアクセスして使用する場合は、オブジェクトの破壊を使用します。エスリント:優先破壊

    なぜでしょうか。破棄すると、これらのプロパティの一時的な参照を作成したり、オブジェクトに繰り返しアクセスしたりする必要がなくなります。オブジェクトアクセスを繰り返すと、より多くの反復的なコードが作成され、より多くの読み取りが必要になり、間違いの機会が増えます。オブジェクトを破棄すると、ブロック全体を読み取って何が使用されているかを判断する必要はなく、ブロックで使用されるオブジェクト構造の定義の単一のサイトも提供されます。

    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    
      return `${firstName} ${lastName}`;
    }
    
    // good
    function getFullName(user) {
      const { firstName, lastName } = user;
      return `${firstName} ${lastName}`;
    }
    
    // best
    function getFullName({ firstName, lastName }) {
      return `${firstName} ${lastName}`;
    }

  • 5.2 配列破壊を使用する。エスリント:優先破壊

    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    
    // good
    const [first, second] = arr;

  • 5.3配列の破壊ではなく、複数の戻り値に対してオブジェクトの破壊を使用します。

    なぜでしょうか。時間の経過と共に新しいプロパティを追加したり、呼び出しサイトを中断することなく順序を変更したりできます。

    // bad
    function processInput(input) {
      // then a miracle occurs
      return [left, right, top, bottom];
    }
    
    // the caller needs to think about the order of return data
    const [left, __, top] = processInput(input);
    
    // good
    function processInput(input) {
      // then a miracle occurs
      return { left, right, top, bottom };
    }
    
    // the caller selects only the data they need
    const { left, top } = processInput(input);

一番上に戻る

ストリングス

  • 6.1 文字列には一重引用符を使用します。エスリント:引用符

    ''

    // bad
    const name = "Capt. Janeway";
    
    // bad - template literals should contain interpolation or newlines
    const name = `Capt. Janeway`;
    
    // good
    const name = 'Capt. Janeway';

  • 6.2 行が 100 文字を超える文字列は、文字列連結を使用して複数行にまたがって記述しないでください。

    なぜでしょうか。壊れた文字列は操作が難しく、コードを検索しにくくします。

    // bad
    const errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // bad
    const errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';
    
    // good
    const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';

  • 6.3 プログラムで文字列を作成する場合は、連結ではなくテンプレート文字列を使用します。eslint: 優先テンプレートテンプレート中括弧間隔

    なぜでしょうか。テンプレート文字列は、適切な改行と文字列補間機能を備えた読みやすく簡潔な構文を提供します。

    // bad
    function sayHi(name) {
      return 'How are you, ' + name + '?';
    }
    
    // bad
    function sayHi(name) {
      return ['How are you, ', name, '?'].join();
    }
    
    // bad
    function sayHi(name) {
      return `How are you, ${ name }?`;
    }
    
    // good
    function sayHi(name) {
      return `How are you, ${name}?`;
    }

  • 6.4文字列に使用しないでください、それはあまりにも多くの脆弱性を開きます。エスリント:評価なし
    eval()

  • 6.5 文字列内の文字を不必要にエスケープしないでください。エスリント:役に立たない脱出

    なぜでしょうか。バックスラッシュは読みやすさを損なうため、必要な場合にのみ存在する必要があります。

    // bad
    const foo = '\'this\' \i\s \"quoted\"';
    
    // good
    const foo = '\'this\' is "quoted"';
    const foo = `my name is '${name}'`;

一番上に戻る

関数

  • 7.1 関数宣言の代わりに名前付き関数式を使用する。エスリント:ファンクスタイル

    なぜでしょうか。関数宣言はホイストされているため、ファイルで定義する前に関数を参照するのは簡単です。これは、可読性と保守性を損ないます。関数の定義が大きく複雑で、ファイルの残りの部分の理解を妨げている場合は、おそらくそれを独自のモジュールに抽出する時が来ました!名前が包含変数から推論されるかどうかに関係なく、式に明示的に名前を付けることを忘れないでください(これは、最近のブラウザやBabelなどのコンパイラを使用する場合によく見られます)。これにより、エラーの呼び出し履歴に関する仮定が排除されます。(ディスカッション)

    // bad
    function foo() {
      // ...
    }
    
    // bad
    const foo = function () {
      // ...
    };
    
    // good
    // lexical name distinguished from the variable-referenced invocation(s)
    const short = function longUniqueMoreDescriptiveLexicalFoo() {
      // ...
    };

  • 7.2 すぐに呼び出された関数式を括弧で囲んで折り返します。エスリント:ラップIIFE

    なぜでしょうか。すぐに呼び出される関数式は単一のユニットであり、両方をラップし、その呼び出しparensはparensでこれをきれいに表現します。モジュールがいたるところにある世界では、IIFEはほとんど必要ありません。

    // immediately-invoked function expression (IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());

  • 7.3 関数以外のブロック (, など) で関数を宣言しないでください。代わりに、関数を変数に割り当てます。ブラウザはそれを可能にしますが、それらはすべてそれを異なって解釈します、それは悪いニュースです。ESLINT: ループ機能なし
    if
    while

  • 7.4 注: ECMA-262 では、a をステートメントのリストとして定義しています。関数宣言はステートメントではありません。

    block

    // bad
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // good
    let test;
    if (currentUser) {
      test = () => {
        console.log('Yup.');
      };
    }

  • 7.5 パラメータに名前を付けないでください。これは、すべての関数スコープに与えられるオブジェクトよりも優先されます。

    arguments
    arguments

    // bad
    function foo(name, options, arguments) {
      // ...
    }
    
    // good
    function foo(name, options, args) {
      // ...
    }

  • 7.6 使用しない 代わりに REST 構文を使用することを選択します。eslint: prefer-rest-params

    arguments
    ...

    なぜでしょうか。 は、どの引数をプルするかについて明示しています。さらに、残りの引数は実際の配列であり、単に配列のようなものではありません。

    ...
    arguments

    // bad
    function concatenateAll() {
      const args = Array.prototype.slice.call(arguments);
      return args.join('');
    }
    
    // good
    function concatenateAll(...args) {
      return args.join('');
    }

  • 7.7 関数の引数を変更するのではなく、デフォルトのパラメーター構文を使用します。

    // really bad
    function handleThings(opts) {
      // No! We shouldn’t mutate function arguments.
      // Double bad: if opts is falsy it'll be set to an object which may
      // be what you want but it can introduce subtle bugs.
      opts = opts || {};
      // ...
    }
    
    // still bad
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }

  • 7.8 デフォルトのパラメータで副作用を避ける。

    なぜでしょうか。彼らは推論するのに混乱しています。

    let b = 1;
    // bad
    function count(a = b++) {
      console.log(a);
    }
    count();  // 1
    count();  // 2
    count(3); // 3
    count();  // 3

  • 7.9 デフォルトのパラメータは常に最後にします。eslint: default-param-last

    // bad
    function handleThings(opts = {}, name) {
      // ...
    }
    
    // good
    function handleThings(name, opts = {}) {
      // ...
    }

  • 7.10 Function コンストラクタを使用して新しい関数を作成しないでください。ESLINT: no-new-func

    なぜでしょうか。この方法で関数を作成すると、脆弱性を開く と同様に文字列が評価されます。

    eval()

    // bad
    const add = new Function('a', 'b', 'return a + b');
    
    // still bad
    const subtract = Function('a', 'b', 'return a - b');

  • 7.11 関数シグネチャの間隔。ESLINT: スペース・ビフォア・ファンクション・パレン・スペース・ビフォア・ブロック

    なぜでしょうか。一貫性は良好であり、名前を追加または削除するときにスペースを追加または削除する必要はありません。

    // bad
    const f = function(){};
    const g = function (){};
    const h = function() {};
    
    // good
    const x = function () {};
    const y = function a() {};

  • 7.12 パラメータを変更しないでください。ESLINT: パラメータ再割り当てなし

    なぜでしょうか。パラメーターとして渡されたオブジェクトを操作すると、最初の呼び出し元で不要な変数の副作用が発生する可能性があります。

    // bad
    function f1(obj) {
      obj.key = 1;
    }
    
    // good
    function f2(obj) {
      const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
    }

  • 7.13 パラメータを再割り当てしない。ESLINT: パラメータ再割り当てなし

    なぜでしょうか。パラメーターを再割り当てすると、特にオブジェクトにアクセスするときに予期しない動作が発生する可能性があります。また、特にV8では最適化の問題が発生する可能性があります。

    arguments

    // bad
    function f1(a) {
      a = 1;
      // ...
    }
    
    function f2(a) {
      if (!a) { a = 1; }
      // ...
    }
    
    // good
    function f3(a) {
      const b = a || 1;
      // ...
    }
    
    function f4(a = 1) {
      // ...
    }

  • 7.14 可変個引数関数を呼び出すためにスプレッド構文の使用を優先します。エスリント:優先スプレッド

    ...

    なぜでしょうか。それはよりクリーンです、あなたは文脈を提供する必要はありません、そしてあなたは簡単に作曲することはできません。

    new
    apply

    // bad
    const x = [1, 2, 3, 4, 5];
    console.log.apply(console, x);
    
    // good
    const x = [1, 2, 3, 4, 5];
    console.log(...x);
    
    // bad
    new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
    
    // good
    new Date(...[2016, 8, 5]);

  • 7.15 複数行のシグネチャまたは呼び出しを持つ関数は、このガイドの他のすべての複数行リストと同様に、各項目を単独で行に、最後の項目に末尾のコンマを付けてインデントする必要があります。ESLINT: 関数-括弧 - 改行

    // bad
    function foo(bar,
                 baz,
                 quux) {
      // ...
    }
    
    // good
    function foo(
      bar,
      baz,
      quux,
    ) {
      // ...
    }
    
    // bad
    console.log(foo,
      bar,
      baz);
    
    // good
    console.log(
      foo,
      bar,
      baz,
    );

一番上に戻る

矢印関数

  • 8.1 (インラインコールバックを渡すときなど) 匿名関数を使用する必要がある場合は、矢印関数表記を使用します。ESLINT:優先矢印コールバック矢印間隔

    なぜでしょうか。これは、 のコンテキストで実行される関数のバージョンを作成します。これは通常、必要なものであり、より簡潔な構文です。

    this

    なぜ駄目なのですか。かなり複雑な関数がある場合は、そのロジックを独自の名前付き関数式に移動することができます。

    // bad
    [1, 2, 3].map(function (x) {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });

  • 8.2 関数本体が副作用のないを返す単一のステートメントで構成されている場合は、中括弧を省略して暗黙の戻り値を使用します。それ以外の場合は、中括弧を保持し、ステートメントを使用します。エスリント:アローパレンスアローボディスタイル

    return

    なぜでしょうか。構文上の砂糖。複数の関数が連鎖しているときによく読みます。

    // bad
    [1, 2, 3].map((number) => {
      const nextNumber = number + 1;
      `A string containing the ${nextNumber}.`;
    });
    
    // good
    [1, 2, 3].map((number) => `A string containing the ${number + 1}.`);
    
    // good
    [1, 2, 3].map((number) => {
      const nextNumber = number + 1;
      return `A string containing the ${nextNumber}.`;
    });
    
    // good
    [1, 2, 3].map((number, index) => ({
      [index]: number,
    }));
    
    // No implicit return with side effects
    function foo(callback) {
      const val = callback();
      if (val === true) {
        // Do something if callback returns true
      }
    }
    
    let bool = false;
    
    // bad
    foo(() => bool = true);
    
    // good
    foo(() => {
      bool = true;
    });

  • 8.3 式が複数行にまたがる場合は、読みやすくするために括弧で囲みます。

    なぜでしょうか。関数の開始位置と終了位置を明確に示します。

    // bad
    ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    );
    
    // good
    ['get', 'post', 'put'].map((httpMethod) => (
      Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    ));

  • 8.4 明確さと一貫性を保つために、引数を必ず括弧で囲みます。エスリント:矢印括弧

    なぜでしょうか。引数を追加または削除するときの差分チャーンを最小限に抑えます。

    // bad
    [1, 2, 3].map(x => x * x);
    
    // good
    [1, 2, 3].map((x) => x * x);
    
    // bad
    [1, 2, 3].map(number => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));
    
    // good
    [1, 2, 3].map((number) => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));
    
    // bad
    [1, 2, 3].map(x => {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });

  • 8.5 矢印関数の構文 () と比較演算子 (, ) を混同しないようにします。エスリント:紛らわしい矢印

    =>
    <=
    >=

    // bad
    const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize;
    
    // bad
    const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;
    
    // good
    const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize);
    
    // good
    const itemHeight = (item) => {
      const { height, largeSize, smallSize } = item;
      return height <= 256 ? largeSize : smallSize;
    };

  • 8.6 暗黙の戻り値を持つ矢印関数本体の位置を強制します。エスリント:暗黙の矢印改行

    // bad
    (foo) =>
      bar;
    
    (foo) =>
      (bar);
    
    // good
    (foo) => bar;
    (foo) => (bar);
    (foo) => (
       bar
    )

一番上に戻る

クラスとコンストラクタ

  • 9.1 常に .直接操作することは避けてください。

    class
    prototype

    なぜでしょうか。 構文はより簡潔で、推論が容易です。

    class

    // bad
    function Queue(contents = []) {
      this.queue = [...contents];
    }
    Queue.prototype.pop = function () {
      const value = this.queue[0];
      this.queue.splice(0, 1);
      return value;
    };
    
    // good
    class Queue {
      constructor(contents = []) {
        this.queue = [...contents];
      }
      pop() {
        const value = this.queue[0];
        this.queue.splice(0, 1);
        return value;
      }
    }

  • 9.2 継承に使用します。

    extends

    なぜでしょうか。これは、 を壊すことなくプロトタイプ機能を継承するための組み込みの方法です。

    instanceof

    // bad
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function () {
      return this.queue[0];
    };
    
    // good
    class PeekableQueue extends Queue {
      peek() {
        return this.queue[0];
      }
    }

  • 9.3 メソッドはメソッドチェーンのヘルプに戻ることができます。

    this

    // bad
    Jedi.prototype.jump = function () {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function (height) {
      this.height = height;
    };
    
    const luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20); // => undefined
    
    // good
    class Jedi {
      jump() {
        this.jumping = true;
        return this;
      }
    
      setHeight(height) {
        this.height = height;
        return this;
      }
    }
    
    const luke = new Jedi();
    
    luke.jump()
      .setHeight(20);

  • 9.4 カスタムメソッドを書いても大丈夫ですが、それが正常に動作し、副作用を引き起こさないことを確認してください。

    toString()

    class Jedi {
      constructor(options = {}) {
        this.name = options.name || 'no name';
      }
    
      getName() {
        return this.name;
      }
    
      toString() {
        return `Jedi - ${this.getName()}`;
      }
    }

  • 9.5 クラスにはデフォルトのコンストラクタが指定されていない場合、デフォルトのコンストラクタがあります。空のコンストラクター関数や、親クラスにデリゲートするだけのコンストラクター関数は不要です。eslint: 役に立たないコンストラクタ

    // bad
    class Jedi {
      constructor() {}
    
      getName() {
        return this.name;
      }
    }
    
    // bad
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
      }
    }
    
    // good
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
        this.name = 'Rey';
      }
    }

  • 9.6 クラスメンバーの重複を避ける。エスリント:重複禁止クラスのメンバー

    なぜでしょうか。重複するクラスメンバー宣言は、最後の宣言を暗黙のうちに優先します - 重複を持つことはほぼ確実にバグです。

    // bad
    class Foo {
      bar() { return 1; }
      bar() { return 2; }
    }
    
    // good
    class Foo {
      bar() { return 1; }
    }
    
    // good
    class Foo {
      bar() { return 2; }
    }

  • 9.7 クラスメソッドは、外部ライブラリまたはフレームワークが特定の非静的メソッドを使用する必要がない限り、静的メソッドを使用するか、静的メソッドにする必要があります。インスタンスメソッドであることは、受信者のプロパティに基づいて異なる動作をすることを示す必要があります。eslint: class-methods-use-this

    this

    // bad
    class Foo {
      bar() {
        console.log('bar');
      }
    }
    
    // good - this is used
    class Foo {
      bar() {
        console.log(this.bar);
      }
    }
    
    // good - constructor is exempt
    class Foo {
      constructor() {
        // ...
      }
    }
    
    // good - static methods aren't expected to use this
    class Foo {
      static bar() {
        console.log('bar');
      }
    }

一番上に戻る

モジュール

  • 10.1 非標準のモジュール システムでは、常にモジュール (/) を使用してください。いつでもお好みのモジュールシステムにトランスパイルできます。

    import
    export

    なぜでしょうか。モジュールは未来です、今未来を使い始めましょう。

    // bad
    const AirbnbStyleGuide = require('./AirbnbStyleGuide');
    module.exports = AirbnbStyleGuide.es6;
    
    // ok
    import AirbnbStyleGuide from './AirbnbStyleGuide';
    export default AirbnbStyleGuide.es6;
    
    // best
    import { es6 } from './AirbnbStyleGuide';
    export default es6;

  • 10.2 ワイルドカード インポートを使用しない。

    なぜでしょうか。これにより、デフォルトのエクスポートが 1 つになります。

    // bad
    import * as AirbnbStyleGuide from './AirbnbStyleGuide';
    
    // good
    import AirbnbStyleGuide from './AirbnbStyleGuide';

  • 10.3 また、インポートから直接エクスポートしないでください。

    なぜでしょうか。ワンライナーは簡潔ですが、インポートする明確な方法とエクスポートする明確な方法が1つあると、一貫性が保たれます。

    // bad
    // filename es6.js
    export { es6 as default } from './AirbnbStyleGuide';
    
    // good
    // filename es6.js
    import { es6 } from './AirbnbStyleGuide';
    export default es6;

  • 10.4 1 か所のパスからのみインポートします。 エスリント:重複インポートなし

    なぜでしょうか。同じパスからインポートする複数の行があると、コードの保守が難しくなる可能性があります。

    // bad
    import foo from 'foo';
    // … some other imports … //
    import { named1, named2 } from 'foo';
    
    // good
    import foo, { named1, named2 } from 'foo';
    
    // good
    import foo, {
      named1,
      named2,
    } from 'foo';

  • 10.5 変更可能なバインディングをエクスポートしないでください。 ESLINT: インポート/変更不可能なエクスポート

    なぜでしょうか。一般的には変更を避ける必要がありますが、特に可変バインディングをエクスポートする場合は避けてください。この手法は特殊なケースで必要になる場合がありますが、一般的には定数参照のみをエクスポートする必要があります。

    // bad
    let foo = 3;
    export { foo };
    
    // good
    const foo = 3;
    export { foo };

  • 10.6 エクスポートが 1 つのモジュールでは、名前付きエクスポートよりもデフォルトのエクスポートを優先します。 ESLINT: インポート/優先デフォルト-エクスポート

    なぜでしょうか。1つのものだけをエクスポートするファイルを増やすことを奨励するため、読みやすさと保守性が向上します。

    // bad
    export function foo() {}
    
    // good
    export default function foo() {}

  • 10.7 すべての s を非インポートステートメントの上に置きます。 エスリント:インポート/最初

    import

    なぜでしょうか。は吊り上げられているので、すべてを一番上に保つと、驚くべき動作を防ぐことができます。

    import

    // bad
    import foo from 'foo';
    foo.init();
    
    import bar from 'bar';
    
    // good
    import foo from 'foo';
    import bar from 'bar';
    
    foo.init();

  • 10.8 複数行のインポートは、複数行の配列やオブジェクトリテラルと同様にインデントする必要があります。 ESLINT: オブジェクト - 中線 - 改行

    なぜでしょうか。中括弧は、スタイルガイドの他のすべての中括弧ブロックと同じインデント規則に従い、末尾のコンマも同様です。

    // bad
    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';
    
    // good
    import {
      longNameA,
      longNameB,
      longNameC,
      longNameD,
      longNameE,
    } from 'path';

  • 10.9 モジュールインポートステートメントでWebpackローダー構文を許可しません。 eslint: インポート/ウェブパックローダーなしの構文

    なぜでしょうか。インポートでWebpack構文を使用するため、コードがモジュールバンドラーに結合されます。のローダー構文を使用することをお勧めします。

    webpack.config.js

    // bad
    import fooSass from 'css!sass!foo.scss';
    import barCss from 'style!css!bar.css';
    
    // good
    import fooSass from 'foo.scss';
    import barCss from 'bar.css';

  • 10.10 ファイル名拡張子を含めない ESLINT: インポート/拡張機能

    なぜでしょうか。拡張機能を含めると、リファクタリングが禁止され、すべてのコンシューマーにインポートするモジュールの実装の詳細が不適切にハードコードされます。

    // bad
    import foo from './foo.js';
    import bar from './bar.jsx';
    import baz from './baz/index.jsx';
    
    // good
    import foo from './foo';
    import bar from './bar';
    import baz from './baz';

一番上に戻る

イテレータとジェネレータ

  • 11.1 イテレータを使わない。やのようなループの代わりにJavaScriptの高階関数を好む。eslint: イテレータなし制限なし構文

    for-in
    for-of

    なぜでしょうか。これにより、不変のルールが適用されます。値を返す純粋な関数を扱うことは、副作用よりも推論が簡単です。

    使う///////。。。配列を反復処理し、/ / 配列を生成してオブジェクトを反復処理できるようにします。

    map()
    every()
    filter()
    find()
    findIndex()
    reduce()
    some()
    Object.keys()
    Object.values()
    Object.entries()

    const numbers = [1, 2, 3, 4, 5];
    
    // bad
    let sum = 0;
    for (let num of numbers) {
      sum += num;
    }
    sum === 15;
    
    // good
    let sum = 0;
    numbers.forEach((num) => {
      sum += num;
    });
    sum === 15;
    
    // best (use the functional force)
    const sum = numbers.reduce((total, num) => total + num, 0);
    sum === 15;
    
    // bad
    const increasedByOne = [];
    for (let i = 0; i < numbers.length; i++) {
      increasedByOne.push(numbers[i] + 1);
    }
    
    // good
    const increasedByOne = [];
    numbers.forEach((num) => {
      increasedByOne.push(num + 1);
    });
    
    // best (keeping it functional)
    const increasedByOne = numbers.map((num) => num + 1);

  • 11.2 今のところジェネレータは使用しないでください。

    なぜでしょうか。それらはES5にうまくトランスパイルしません。

  • 11.3 ジェネレータを使用する必要がある場合、または当社のアドバイスを無視する場合は、ジェネレータの機能シグネチャの間隔が適切に配置されていることを確認してください。ESLINT: ジェネレーター-星の間隔

    なぜでしょうか。 であり、 は同じ概念キーワードの一部である - は の修飾子ではない は、 とは異なる一意の構成体である。

    function
    *
    *
    function
    function*
    function

    // bad
    function * foo() {
      // ...
    }
    
    // bad
    const bar = function * () {
      // ...
    };
    
    // bad
    const baz = function *() {
      // ...
    };
    
    // bad
    const quux = function*() {
      // ...
    };
    
    // bad
    function*foo() {
      // ...
    }
    
    // bad
    function *foo() {
      // ...
    }
    
    // very bad
    function
    *
    foo() {
      // ...
    }
    
    // very bad
    const wat = function
    *
    () {
      // ...
    };
    
    // good
    function* foo() {
      // ...
    }
    
    // good
    const foo = function* () {
      // ...
    };

一番上に戻る

プロパティ

  • 12.1 プロパティにアクセスするときにドット表記を使用します。エスリント: ドット表記

    const luke = {
      jedi: true,
      age: 28,
    };
    
    // bad
    const isJedi = luke['jedi'];
    
    // good
    const isJedi = luke.jedi;

  • 12.2 変数を持つプロパティにアクセスするときに括弧表記を使用します。

    []

    const luke = {
      jedi: true,
      age: 28,
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    const isJedi = getProp('jedi');

  • 12.3 べき乗を計算するときに指数演算子を使用します。エスリント:制限のないプロパティ

    **

    // bad
    const binary = Math.pow(2, 10);
    
    // good
    const binary = 2 ** 10;

一番上に戻る

変数

  • 13.1 変数を宣言するには、常に or を使用します。そうしないと、グローバル変数になります。グローバル名前空間を汚染しないようにする必要があります。キャプテンプラネットは私たちにそれを警告しました。ESLINT: no-undef prefer-const

    const
    let

    // bad
    superPower = new SuperPower();
    
    // good
    const superPower = new SuperPower();

  • 13.2 変数または代入ごとに 1 つの OR 宣言を使用します。エスリント: 1-変数

    const
    let

    なぜでしょうか。この方法で新しい変数宣言を追加する方が簡単で、a を a に交換したり、句読点のみの差分を導入したりすることを心配する必要はありません。また、すべての宣言を一度にジャンプするのではなく、デバッガーを使用して各宣言をステップ実行することもできます。

    ;
    ,

    // bad
    const items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
    
    // bad
    // (compare to above, and try to spot the mistake)
    const items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';
    
    // good
    const items = getItems();
    const goSportsTeam = true;
    const dragonball = 'z';

  • 13.3 すべての をグループ化してから、すべての をグループ化します。

    const
    let

    なぜでしょうか。これは、後で以前に割り当てられた変数の1つに応じて変数を割り当てる必要がある場合に便利です。

    // bad
    let i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // bad
    let i;
    const items = getItems();
    let dragonball;
    const goSportsTeam = true;
    let len;
    
    // good
    const goSportsTeam = true;
    const items = getItems();
    let dragonball;
    let i;
    let length;

  • 13.4 必要な場所に変数を割り当てますが、適切な場所に配置します。

    なぜでしょうか。 ブロックスコープであり、関数スコープではありません。

    let
    const

    // bad - unnecessary function call
    function checkName(hasName) {
      const name = getName();
    
      if (hasName === 'test') {
        return false;
      }
    
      if (name === 'test') {
        this.setName('');
        return false;
      }
    
      return name;
    }
    
    // good
    function checkName(hasName) {
      if (hasName === 'test') {
        return false;
      }
    
      const name = getName();
    
      if (name === 'test') {
        this.setName('');
        return false;
      }
    
      return name;
    }

  • 13.5 変数の割り当てを連鎖させない。ESLINT: 複数割り当てなし

    なぜでしょうか。変数の割り当てを連鎖させると、暗黙的なグローバル変数が作成されます。

    // bad
    (function example() {
      // JavaScript interprets this as
      // let a = ( b = ( c = 1 ) );
      // The let keyword only applies to variable a; variables b and c become
      // global variables.
      let a = b = c = 1;
    }());
    
    console.log(a); // throws ReferenceError
    console.log(b); // 1
    console.log(c); // 1
    
    // good
    (function example() {
      let a = 1;
      let b = a;
      let c = a;
    }());
    
    console.log(a); // throws ReferenceError
    console.log(b); // throws ReferenceError
    console.log(c); // throws ReferenceError
    
    // the same applies for `const`

  • 13.6 単項の増分と減分 (, ) の使用は避けてください。エスリントプラスプラスなし

    ++
    --

    なぜでしょうか。eslint のドキュメントによると、単項インクリメントおよびデクリメントステートメントはセミコロンの自動挿入の対象となり、アプリケーション内で値をインクリメントまたはデクリメントするとサイレントエラーが発生する可能性があります。また、 の代わりに or のようなステートメントで値を変化させる方が表現力豊かです。単項インクリメントおよびデクリメントステートメントを許可しないと、意図せずに値を事前インクリメント/プリデクリメントすることも防止され、プログラム内で予期しない動作が発生する可能性があります。

    num += 1
    num++
    num ++

    // bad
    
    const array = [1, 2, 3];
    let num = 1;
    num++;
    --num;
    
    let sum = 0;
    let truthyCount = 0;
    for (let i = 0; i < array.length; i++) {
      let value = array[i];
      sum += value;
      if (value) {
        truthyCount++;
      }
    }
    
    // good
    
    const array = [1, 2, 3];
    let num = 1;
    num += 1;
    num -= 1;
    
    const sum = array.reduce((a, b) => a + b, 0);
    const truthyCount = array.filter(Boolean).length;

  • 13.7 課題の前後に改行を入れないようにする。割り当てが max-len に違反している場合は、値を paren で囲みます。エスリント演算子-改行

    =

    なぜでしょうか。周囲を改行すると、割り当ての値が難読化される可能性があります。

    =

    // bad
    const foo =
      superLongLongLongLongLongLongLongLongFunctionName();
    
    // bad
    const foo
      = 'superLongLongLongLongLongLongLongLongString';
    
    // good
    const foo = (
      superLongLongLongLongLongLongLongLongFunctionName()
    );
    
    // good
    const foo = 'superLongLongLongLongLongLongLongLongString';

  • 13.8 未使用の変数を許可しません。ESLINT: 未使用の変数なし

    なぜでしょうか。宣言され、コード内のどこにも使用されていない変数は、リファクタリングが不完全なためにエラーである可能性が高くなります。このような変数はコード内のスペースを占有し、読者による混乱を招く可能性があります。

    // bad
    
    const some_unused_var = 42;
    
    // Write-only variables are not considered as used.
    let y = 10;
    y = 5;
    
    // A read for a modification of itself is not considered as used.
    let z = 0;
    z = z + 1;
    
    // Unused function arguments.
    function getX(x, y) {
        return x;
    }
    
    // good
    
    function getXPlusY(x, y) {
      return x + y;
    }
    
    const x = 1;
    const y = a + 2;
    
    alert(getXPlusY(x, y));
    
    // 'type' is ignored even if unused because it has a rest property sibling.
    // This is a form of extracting an object that omits the specified keys.
    const { type, ...coords } = data;
    // 'coords' is now the 'data' object without its 'type' property.

一番上に戻る

巻き上げ

  • 14.1宣言は最も近い囲み関数スコープの一番上に吊り上げられますが、その割り当てはそうではありません。 宣言は、時間的デッドゾーン(TDZ)と呼ばれる新しい概念に恵まれています。typeofがもはや安全でなくなった理由を知ることは重要です。

    var
    const
    let

    // we know this wouldn’t work (assuming there
    // is no notDefined global variable)
    function example() {
      console.log(notDefined); // => throws a ReferenceError
    }
    
    // creating a variable declaration after you
    // reference the variable will work due to
    // variable hoisting. Note: the assignment
    // value of `true` is not hoisted.
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // the interpreter is hoisting the variable
    // declaration to the top of the scope,
    // which means our example could be rewritten as:
    function example() {
      let declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
    
    // using const and let
    function example() {
      console.log(declaredButNotAssigned); // => throws a ReferenceError
      console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
      const declaredButNotAssigned = true;
    }

  • 14.2 匿名関数式は変数名をホイアップしますが、関数代入は上げません。

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }

  • 14.3 名前付き関数式は、関数名や関数本体ではなく、変数名をホイアップします。

    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // the same is true when the function name
    // is the same as the variable name.
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      };
    }

  • 14.4 関数宣言は、その名前と関数本体を持ち上げます。

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
  • 詳細については、Ben CherryによるJavaScript Scopeping & Hoistingを参照してください。

一番上に戻る

比較演算子と等価

  • 15.1 使用および以上および.Eslint: EQEQEQ
    ===
    !==
    ==
    !=

  • 15.2 ステートメントのような条件ステートメントは、抽象メソッドで強制を使用して式を評価し、常に次の単純なルールに従います。

    if
    ToBoolean

    • オブジェクトは true と評価されます
    • 未定義と評価されます
    • ヌルはと評価されます
    • ブール値はブール値に評価されます
    • 数値は+0、-0、または NaN の場合は false と評価され、それ以外の場合は true と評価されます。
    • 文字列は、空の文字列の場合は false と評価され、それ以外の場合は true と評価されます。
      ''
    if ([0] && []) {
      // true
      // an array (even an empty one) is an object, objects will evaluate to true
    }

  • 15.3 ブール値にはショートカットを使用し、文字列と数値には明示的な比較を使用します。

    // bad
    if (isValid === true) {
      // ...
    }
    
    // good
    if (isValid) {
      // ...
    }
    
    // bad
    if (name) {
      // ...
    }
    
    // good
    if (name !== '') {
      // ...
    }
    
    // bad
    if (collection.length) {
      // ...
    }
    
    // good
    if (collection.length > 0) {
      // ...
    }

  • 15.5 中括弧を使用して、字句宣言を含むブロックと句を作成します(例:、、および)。エスリント: 大文字と小文字なしの宣言

    case
    default
    let
    const
    function
    class

    なぜでしょうか。字句宣言はブロック全体に表示されますが、割り当てられた場合にのみ初期化され、到達したときにのみ発生します。これにより、複数の句が同じことを定義しようとすると問題が発生します。

    switch
    case
    case

    // bad
    switch (foo) {
      case 1:
        let x = 1;
        break;
      case 2:
        const y = 2;
        break;
      case 3:
        function f() {
          // ...
        }
        break;
      default:
        class C {}
    }
    
    // good
    switch (foo) {
      case 1: {
        let x = 1;
        break;
      }
      case 2: {
        const y = 2;
        break;
      }
      case 3: {
        function f() {
          // ...
        }
        break;
      }
      case 4:
        bar();
        break;
      default: {
        class C {}
      }
    }

  • 15.6 三項はネストしてはならず、通常は単一行の式であるべきです。エスリント:ネストされていない三元

    // bad
    const foo = maybe1 > maybe2
      ? "bar"
      : value1 > value2 ? "baz" : null;
    
    // split into 2 separated ternary expressions
    const maybeNull = value1 > value2 ? 'baz' : null;
    
    // better
    const foo = maybe1 > maybe2
      ? 'bar'
      : maybeNull;
    
    // best
    const foo = maybe1 > maybe2 ? 'bar' : maybeNull;

  • 15.7 不要な三項ステートメントは避けてください。ESLINT: 不要な三元なし

    // bad
    const foo = a ? a : b;
    const bar = c ? true : false;
    const baz = c ? false : true;
    const quux = a != null ? a : b;
    
    // good
    const foo = a || b;
    const bar = !!c;
    const baz = !c;
    const quux = a ?? b;

  • 15.8演算子を混在させる場合は、括弧で囲みます。唯一の例外は、標準の算術演算子です:、、およびそれらの優先順位は広く理解されているためです。括弧内と括弧で囲むことをお勧めします。括弧が混在すると優先順位があいまいになる可能性があるためです。 ESLINT: 混合演算子なし

    +
    -
    **
    /
    *

    なぜでしょうか。これにより、読みやすさが向上し、開発者の意図が明確になります。

    // bad
    const foo = a && b < 0 || c > 0 || d + 1 === 0;
    
    // bad
    const bar = a ** b - 5 % d;
    
    // bad
    // one may be confused into thinking (a || b) && c
    if (a || b && c) {
      return d;
    }
    
    // bad
    const bar = a + b / c * d;
    
    // good
    const foo = (a && b < 0) || c > 0 || (d + 1 === 0);
    
    // good
    const bar = a ** b - (5 % d);
    
    // good
    if (a || (b && c)) {
      return d;
    }
    
    // good
    const bar = a + (b / c) * d;

一番上に戻る

ブロック

  • 16.1すべての複数行ブロックで中括弧を使用します。eslint: 非ブロックステートメント - 本体位置

    // bad
    if (test)
      return false;
    
    // good
    if (test) return false;
    
    // good
    if (test) {
      return false;
    }
    
    // bad
    function foo() { return false; }
    
    // good
    function bar() {
      return false;
    }

  • 16.2 複数行のブロックを と で使用している場合は、ブロックの右中括弧と同じ行に配置します。エスリント:ブレーススタイル

    if
    else
    else
    if

    // bad
    if (test) {
      thing1();
      thing2();
    }
    else {
      thing3();
    }
    
    // good
    if (test) {
      thing1();
      thing2();
    } else {
      thing3();
    }

  • 16.3 ブロックが常にステートメントを実行する場合、後続のブロックは不要です。を含むブロックに続くブロック内のAは、複数のブロックに分割できます。エスリント:他には戻りません

    if
    return
    else
    return
    else if
    if
    return
    if

    // bad
    function foo() {
      if (x) {
        return x;
      } else {
        return y;
      }
    }
    
    // bad
    function cats() {
      if (x) {
        return x;
      } else if (y) {
        return y;
      }
    }
    
    // bad
    function dogs() {
      if (x) {
        return x;
      } else {
        if (y) {
          return y;
        }
      }
    }
    
    // good
    function foo() {
      if (x) {
        return x;
      }
    
      return y;
    }
    
    // good
    function cats() {
      if (x) {
        return x;
      }
    
      if (y) {
        return y;
      }
    }
    
    // good
    function dogs(x) {
      if (x) {
        if (z) {
          return y;
        }
      } else {
        return z;
      }
    }

一番上に戻る

制御ステートメント

  • 17.1 制御ステートメント ( など) が長くなりすぎたり、最大行長を超えたりした場合、各 (グループ化された) 条件を新しい行に入れることができます。論理演算子は行を開始する必要があります。

    if
    while

    なぜでしょうか。行の先頭に演算子を要求すると、演算子の配置が維持され、メソッド チェーンと同様のパターンに従います。これにより、複雑なロジックを視覚的に追跡しやすくなり、読みやすさも向上します。

    // bad
    if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
      thing1();
    }
    
    // bad
    if (foo === 123 &&
      bar === 'abc') {
      thing1();
    }
    
    // bad
    if (foo === 123
      && bar === 'abc') {
      thing1();
    }
    
    // bad
    if (
      foo === 123 &&
      bar === 'abc'
    ) {
      thing1();
    }
    
    // good
    if (
      foo === 123
      && bar === 'abc'
    ) {
      thing1();
    }
    
    // good
    if (
      (foo === 123 || bar === 'abc')
      && doesItLookGoodWhenItBecomesThatLong()
      && isThisReallyHappening()
    ) {
      thing1();
    }
    
    // good
    if (foo === 123 && bar === 'abc') {
      thing1();
    }

  • 17.2 制御ステートメントの代わりに選択演算子を使用しないでください。

    // bad
    !isRunning && startRunning();
    
    // good
    if (!isRunning) {
      startRunning();
    }

一番上に戻る

コメント

  • 18.1 複数行コメントに使用します。

    /** ... */

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {
    
      // ...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed-in tag name
     */
    function make(tag) {
    
      // ...
    
      return element;
    }

  • 18.2 単一行のコメントに使用します。コメントの件名の上の改行に 1 行のコメントを配置します。ブロックの最初の行でない限り、コメントの前に空の行を入れます。

    //

    // bad
    const active = true;  // is current tab
    
    // good
    // is current tab
    const active = true;
    
    // bad
    function getType() {
      console.log('fetching type...');
      // set the default type to 'no type'
      const type = this.type || 'no type';
    
      return type;
    }
    
    // good
    function getType() {
      console.log('fetching type...');
    
      // set the default type to 'no type'
      const type = this.type || 'no type';
    
      return type;
    }
    
    // also good
    function getType() {
      // set the default type to 'no type'
      const type = this.type || 'no type';
    
      return type;
    }

  • 18.3 すべてのコメントは、読みやすくするためにスペースで始めます。エスリント:間隔を空けたコメント

    // bad
    //is current tab
    const active = true;
    
    // good
    // is current tab
    const active = true;
    
    // bad
    /**
     *make() returns a new element
     *based on the passed-in tag name
     */
    function make(tag) {
    
      // ...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed-in tag name
     */
    function make(tag) {
    
      // ...
    
      return element;
    }

  • 18.4 コメントの前に、または、再検討が必要な問題を指摘しているのか、実装する必要のある問題の解決策を提案しているのかを他の開発者がすばやく理解できるようにします。これらはアクション可能であるため、通常のコメントとは異なります。アクションは または です。
    FIXME
    TODO
    FIXME: -- need to figure this out
    TODO: -- need to implement

  • 18.5 問題に注釈を付けるために使用します。

    // FIXME:

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // FIXME: shouldn’t use a global here
        total = 0;
      }
    }

  • 18.6 問題の解決策に注釈を付けるために使用します。

    // TODO:

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // TODO: total should be configurable by an options param
        this.total = 0;
      }
    }

一番上に戻る

空白

  • 19.1 2つのスペースに設定されたソフトタブ(スペース文字)を使用します。エスリント: インデント

    // bad
    function foo() {
    ∙∙∙∙let name;
    }
    
    // bad
    function bar() {
    ∙let name;
    }
    
    // good
    function baz() {
    ∙∙let name;
    }

  • 19.2先頭のブレースの前に1つのスペースを配置します。エスリント:ブロック前のスペース

    // bad
    function test(){
      console.log('test');
    }
    
    // good
    function test() {
      console.log('test');
    }
    
    // bad
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog',
    });
    
    // good
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog',
    });

  • 19.3 制御ステートメント(など)の左括弧の前にスペースを1つ入れます。関数呼び出しと宣言では、引数リストと関数名の間にスペースを入れないでください。エスリント: キーワード間隔

    if
    while

    // bad
    if(isJedi) {
      fight ();
    }
    
    // good
    if (isJedi) {
      fight();
    }
    
    // bad
    function fight () {
      console.log ('Swooosh!');
    }
    
    // good
    function fight() {
      console.log('Swooosh!');
    }

  • 19.4 オペレーターをスペースで配置します。ESLINT: space-infix-ops

    // bad
    const x=y+5;
    
    // good
    const x = y + 5;

  • 19.5 ファイルを 1 つの改行文字で終了します。エスリント:最終終了

    // bad
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;
    // bad
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;
    
    // good
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;

  • 19.6 長いメソッドチェーン(2つ以上のメソッドチェーン)を作成する場合はインデントを使用します。先頭のドットを使用します。 行がメソッド呼び出しであり、新しいステートメントではないことを強調します。eslint: チェーン呼び出しごとの改行 プロパティの前に空白がない

    // bad
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    
    // bad
    $('#items').
      find('.selected').
        highlight().
        end().
      find('.open').
        updateCount();
    
    // good
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();
    
    // bad
    const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
        .attr('width', (radius + margin) * 2).append('svg:g')
        .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
        .call(tron.led);
    
    // good
    const leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .classed('led', true)
        .attr('width', (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
        .call(tron.led);
    
    // good
    const leds = stage.selectAll('.led').data(data);
    const svg = leds.enter().append('svg:svg');
    svg.classed('led', true).attr('width', (radius + margin) * 2);
    const g = svg.append('svg:g');
    g.attr('transform', `translate(${radius + margin}, ${radius + margin})`).call(tron.led);

  • 19.7 Leave a blank line after blocks and before the next statement.

    // bad
    if (foo) {
      return bar;
    }
    return baz;
    
    // good
    if (foo) {
      return bar;
    }
    
    return baz;
    
    // bad
    const obj = {
      foo() {
      },
      bar() {
      },
    };
    return obj;
    
    // good
    const obj = {
      foo() {
      },
    
      bar() {
      },
    };
    
    return obj;
    
    // bad
    const arr = [
      function foo() {
      },
      function bar() {
      },
    ];
    return arr;
    
    // good
    const arr = [
      function foo() {
      },
    
      function bar() {
      },
    ];
    
    return arr;

  • 19.8 Do not pad your blocks with blank lines. eslint:

    padded-blocks

    // bad
    function bar() {
    
      console.log(foo);
    
    }
    
    // bad
    if (baz) {
    
      console.log(quux);
    } else {
      console.log(foo);
    
    }
    
    // bad
    class Foo {
    
      constructor(bar) {
        this.bar = bar;
      }
    }
    
    // good
    function bar() {
      console.log(foo);
    }
    
    // good
    if (baz) {
      console.log(quux);
    } else {
      console.log(foo);
    }

  • 19.9 Do not use multiple blank lines to pad your code. eslint:

    no-multiple-empty-lines

    // bad
    class Person {
      constructor(fullName, email, birthday) {
        this.fullName = fullName;
    
    
        this.email = email;
    
    
        this.setAge(birthday);
      }
    
    
      setAge(birthday) {
        const today = new Date();
    
    
        const age = this.getAge(today, birthday);
    
    
        this.age = age;
      }
    
    
      getAge(today, birthday) {
        // ..
      }
    }
    
    // good
    class Person {
      constructor(fullName, email, birthday) {
        this.fullName = fullName;
        this.email = email;
        this.setAge(birthday);
      }
    
      setAge(birthday) {
        const today = new Date();
        const age = getAge(today, birthday);
        this.age = age;
      }
    
      getAge(today, birthday) {
        // ..
      }
    }

  • 19.10 Do not add spaces inside parentheses. eslint:

    space-in-parens

    // bad
    function bar( foo ) {
      return foo;
    }
    
    // good
    function bar(foo) {
      return foo;
    }
    
    // bad
    if ( foo ) {
      console.log(foo);
    }
    
    // good
    if (foo) {
      console.log(foo);
    }

  • 19.11 Do not add spaces inside brackets. eslint:

    array-bracket-spacing

    // bad
    const foo = [ 1, 2, 3 ];
    console.log(foo[ 0 ]);
    
    // good
    const foo = [1, 2, 3];
    console.log(foo[0]);

  • 19.12 Add spaces inside curly braces. eslint:

    object-curly-spacing

    // bad
    const foo = {clark: 'kent'};
    
    // good
    const foo = { clark: 'kent' };

  • 19.13 Avoid having lines of code that are longer than 100 characters (including whitespace). Note: per above, long strings are exempt from this rule, and should not be broken up. eslint:

    max-len

    Why? This ensures readability and maintainability.

    // bad
    const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;
    
    // bad
    $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.'));
    
    // good
    const foo = jsonData
      && jsonData.foo
      && jsonData.foo.bar
      && jsonData.foo.bar.baz
      && jsonData.foo.bar.baz.quux
      && jsonData.foo.bar.baz.quux.xyzzy;
    
    // better
    const foo = jsonData
      ?.foo
      ?.bar
      ?.baz
      ?.quux
      ?.xyzzy;
    
    // good
    $.ajax({
      method: 'POST',
      url: 'https://airbnb.com/',
      data: { name: 'John' },
    })
      .done(() => console.log('Congratulations!'))
      .fail(() => console.log('You have failed this city.'));

  • 19.14 Require consistent spacing inside an open block token and the next token on the same line. This rule also enforces consistent spacing inside a close block token and previous token on the same line. eslint:

    block-spacing

    // bad
    function foo() {return true;}
    if (foo) { bar = 0;}
    
    // good
    function foo() { return true; }
    if (foo) { bar = 0; }

  • 19.15 Avoid spaces before commas and require a space after commas. eslint:

    comma-spacing

    // bad
    const foo = 1,bar = 2;
    const arr = [1 , 2];
    
    // good
    const foo = 1, bar = 2;
    const arr = [1, 2];

  • 19.16 Enforce spacing inside of computed property brackets. eslint:

    computed-property-spacing

    // bad
    obj[foo ]
    obj[ 'foo']
    const x = {[ b ]: a}
    obj[foo[ bar ]]
    
    // good
    obj[foo]
    obj['foo']
    const x = { [b]: a }
    obj[foo[bar]]

  • 19.17 Avoid spaces between functions and their invocations. eslint:

    func-call-spacing

    // bad
    func ();
    
    func
    ();
    
    // good
    func();

  • 19.18 Enforce spacing between keys and values in object literal properties. eslint:

    key-spacing

    // bad
    const obj = { foo : 42 };
    const obj2 = { foo:42 };
    
    // good
    const obj = { foo: 42 };

  • 19.20 Avoid multiple empty lines, only allow one newline at the end of files, and avoid a newline at the beginning of files. eslint:

    no-multiple-empty-lines

    // bad - multiple empty lines
    const x = 1;
    
    
    const y = 2;
    
    // bad - 2+ newlines at end of file
    const x = 1;
    const y = 2;
    
    
    // bad - 1+ newline(s) at beginning of file
    
    const x = 1;
    const y = 2;
    
    // good
    const x = 1;
    const y = 2;

back to top

Commas

  • 20.1 Leading commas: Nope. eslint:

    comma-style

    // bad
    const story = [
        once
      , upon
      , aTime
    ];
    
    // good
    const story = [
      once,
      upon,
      aTime,
    ];
    
    // bad
    const hero = {
        firstName: 'Ada'
      , lastName: 'Lovelace'
      , birthYear: 1815
      , superPower: 'computers'
    };
    
    // good
    const hero = {
      firstName: 'Ada',
      lastName: 'Lovelace',
      birthYear: 1815,
      superPower: 'computers',
    };

  • 20.2 Additional trailing comma: Yup. eslint:

    comma-dangle

    Why? This leads to cleaner git diffs. Also, transpilers like Babel will remove the additional trailing comma in the transpiled code which means you don’t have to worry about the trailing comma problem in legacy browsers.

    // bad - git diff without trailing comma
    const hero = {
         firstName: 'Florence',
    -    lastName: 'Nightingale'
    +    lastName: 'Nightingale',
    +    inventorOf: ['coxcomb chart', 'modern nursing']
    };
    
    // good - git diff with trailing comma
    const hero = {
         firstName: 'Florence',
         lastName: 'Nightingale',
    +    inventorOf: ['coxcomb chart', 'modern nursing'],
    };
    // bad
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully'
    };
    
    const heroes = [
      'Batman',
      'Superman'
    ];
    
    // good
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully',
    };
    
    const heroes = [
      'Batman',
      'Superman',
    ];
    
    // bad
    function createHero(
      firstName,
      lastName,
      inventorOf
    ) {
      // does nothing
    }
    
    // good
    function createHero(
      firstName,
      lastName,
      inventorOf,
    ) {
      // does nothing
    }
    
    // good (note that a comma must not appear after a "rest" element)
    function createHero(
      firstName,
      lastName,
      inventorOf,
      ...heroArgs
    ) {
      // does nothing
    }
    
    // bad
    createHero(
      firstName,
      lastName,
      inventorOf
    );
    
    // good
    createHero(
      firstName,
      lastName,
      inventorOf,
    );
    
    // good (note that a comma must not appear after a "rest" element)
    createHero(
      firstName,
      lastName,
      inventorOf,
      ...heroArgs
    );

back to top

Semicolons

  • 21.1 Yup. eslint:

    semi

    Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called Automatic Semicolon Insertion to determine whether it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.

    // bad - raises exception
    const luke = {}
    const leia = {}
    [luke, leia].forEach((jedi) => jedi.father = 'vader')
    
    // bad - raises exception
    const reaction = "No! That’s impossible!"
    (async function meanwhileOnTheFalcon() {
      // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
      // ...
    }())
    
    // bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI!
    function foo() {
      return
        'search your feelings, you know it to be foo'
    }
    
    // good
    const luke = {};
    const leia = {};
    [luke, leia].forEach((jedi) => {
      jedi.father = 'vader';
    });
    
    // good
    const reaction = 'No! That’s impossible!';
    (async function meanwhileOnTheFalcon() {
      // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
      // ...
    }());
    
    // good
    function foo() {
      return 'search your feelings, you know it to be foo';
    }

    Read more.

back to top

Type Casting & Coercion

  • 22.1 Perform type coercion at the beginning of the statement.

  • 22.2 Strings: eslint:

    no-new-wrappers

    // => this.reviewScore = 9;
    
    // bad
    const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"
    
    // bad
    const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf()
    
    // bad
    const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string
    
    // good
    const totalScore = String(this.reviewScore);

  • 22.3 Numbers: Use for type casting and always with a radix for parsing strings. eslint:

    radix
    no-new-wrappers
    Number
    parseInt

    Why? The function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading whitespace in string is ignored. If radix is or , it is assumed to be except when the number begins with the character pairs or , in which case a radix of 16 is assumed. This differs from ECMAScript 3, which merely discouraged (but allowed) octal interpretation. Many implementations have not adopted this behavior as of 2013. And, because older browsers must be supported, always specify a radix.

    parseInt
    undefined
    0
    10
    0x
    0X

    const inputValue = '4';
    
    // bad
    const val = new Number(inputValue);
    
    // bad
    const val = +inputValue;
    
    // bad
    const val = inputValue >> 0;
    
    // bad
    const val = parseInt(inputValue);
    
    // good
    const val = Number(inputValue);
    
    // good
    const val = parseInt(inputValue, 10);

  • 22.4 If for whatever reason you are doing something wild and is your bottleneck and need to use Bitshift for performance reasons, leave a comment explaining why and what you’re doing.

    parseInt

    // good
    /**
     * parseInt was the reason my code was slow.
     * Bitshifting the String to coerce it to a
     * Number made it a lot faster.
     */
    const val = inputValue >> 0;

  • 22.5 Note: Be careful when using bitshift operations. Numbers are represented as 64-bit values, but bitshift operations always return a 32-bit integer (source). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. Discussion. Largest signed 32-bit Int is 2,147,483,647:

    2147483647 >> 0; // => 2147483647
    2147483648 >> 0; // => -2147483648
    2147483649 >> 0; // => -2147483647

  • 22.6 Booleans: eslint:

    no-new-wrappers

    const age = 0;
    
    // bad
    const hasAge = new Boolean(age);
    
    // good
    const hasAge = Boolean(age);
    
    // best
    const hasAge = !!age;

back to top

Naming Conventions

  • 23.1 Avoid single letter names. Be descriptive with your naming. eslint:

    id-length

    // bad
    function q() {
      // ...
    }
    
    // good
    function query() {
      // ...
    }

  • 23.2 Use camelCase when naming objects, functions, and instances. eslint:

    camelcase

    // bad
    const OBJEcttsssss = {};
    const this_is_my_object = {};
    function c() {}
    
    // good
    const thisIsMyObject = {};
    function thisIsMyFunction() {}

  • 23.3 Use PascalCase only when naming constructors or classes. eslint:

    new-cap

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    const bad = new user({
      name: 'nope',
    });
    
    // good
    class User {
      constructor(options) {
        this.name = options.name;
      }
    }
    
    const good = new User({
      name: 'yup',
    });

  • 23.4 Do not use trailing or leading underscores. eslint:

    no-underscore-dangle

    Why? JavaScript does not have the concept of privacy in terms of properties or methods. Although a leading underscore is a common convention to mean “private”, in fact, these properties are fully public, and as such, are part of your public API contract. This convention might lead developers to wrongly think that a change won’t count as breaking, or that tests aren’t needed. tl;dr: if you want something to be “private”, it must not be observably present.

    // bad
    this.__firstName__ = 'Panda';
    this.firstName_ = 'Panda';
    this._firstName = 'Panda';
    
    // good
    this.firstName = 'Panda';
    
    // good, in environments where WeakMaps are available
    // see https://kangax.github.io/compat-table/es6/#test-WeakMap
    const firstNames = new WeakMap();
    firstNames.set(this, 'Panda');

  • 23.5 Don’t save references to . Use arrow functions or Function#bind.

    this

    // bad
    function foo() {
      const self = this;
      return function () {
        console.log(self);
      };
    }
    
    // bad
    function foo() {
      const that = this;
      return function () {
        console.log(that);
      };
    }
    
    // good
    function foo() {
      return () => {
        console.log(this);
      };
    }

  • 23.6 A base filename should exactly match the name of its default export.

    // file 1 contents
    class CheckBox {
      // ...
    }
    export default CheckBox;
    
    // file 2 contents
    export default function fortyTwo() { return 42; }
    
    // file 3 contents
    export default function insideDirectory() {}
    
    // in some other file
    // bad
    import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
    import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
    import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export
    
    // bad
    import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
    import forty_two from './forty_two'; // snake_case import/filename, camelCase export
    import inside_directory from './inside_directory'; // snake_case import, camelCase export
    import index from './inside_directory/index'; // requiring the index file explicitly
    import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly
    
    // good
    import CheckBox from './CheckBox'; // PascalCase export/import/filename
    import fortyTwo from './fortyTwo'; // camelCase export/import/filename
    import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
    // ^ supports both insideDirectory.js and insideDirectory/index.js

  • 23.7 Use camelCase when you export-default a function. Your filename should be identical to your function’s name.

    function makeStyleGuide() {
      // ...
    }
    
    export default makeStyleGuide;

  • 23.8 Use PascalCase when you export a constructor / class / singleton / function library / bare object.

    const AirbnbStyleGuide = {
      es6: {
      },
    };
    
    export default AirbnbStyleGuide;

  • 23.9 Acronyms and initialisms should always be all uppercased, or all lowercased.

    Why? Names are for readability, not to appease a computer algorithm.

    // bad
    import SmsContainer from './containers/SmsContainer';
    
    // bad
    const HttpRequests = [
      // ...
    ];
    
    // good
    import SMSContainer from './containers/SMSContainer';
    
    // good
    const HTTPRequests = [
      // ...
    ];
    
    // also good
    const httpRequests = [
      // ...
    ];
    
    // best
    import TextMessageContainer from './containers/TextMessageContainer';
    
    // best
    const requests = [
      // ...
    ];

  • 23.10 You may optionally uppercase a constant only if it (1) is exported, (2) is a (it can not be reassigned), and (3) the programmer can trust it (and its nested properties) to never change.

    const

    Why? This is an additional tool to assist in situations where the programmer would be unsure if a variable might ever change. UPPERCASE_VARIABLES are letting the programmer know that they can trust the variable (and its properties) not to change.

    • What about all variables? - This is unnecessary, so uppercasing should not be used for constants within a file. It should be used for exported constants however.
      const
    • What about exported objects? - Uppercase at the top level of export (e.g. ) and maintain that all nested properties do not change.
      EXPORTED_OBJECT.key
    // bad
    const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file';
    
    // bad
    export const THING_TO_BE_CHANGED = 'should obviously not be uppercased';
    
    // bad
    export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables';
    
    // ---
    
    // allowed but does not supply semantic value
    export const apiKey = 'SOMEKEY';
    
    // better in most cases
    export const API_KEY = 'SOMEKEY';
    
    // ---
    
    // bad - unnecessarily uppercases key while adding no semantic value
    export const MAPPING = {
      KEY: 'value'
    };
    
    // good
    export const MAPPING = {
      key: 'value',
    };

back to top

Accessors

  • 24.1 Accessor functions for properties are not required.

  • 24.2 Do not use JavaScript getters/setters as they cause unexpected side effects and are harder to test, maintain, and reason about. Instead, if you do make accessor functions, use and .

    getVal()
    setVal('hello')

    // bad
    class Dragon {
      get age() {
        // ...
      }
    
      set age(value) {
        // ...
      }
    }
    
    // good
    class Dragon {
      getAge() {
        // ...
      }
    
      setAge(value) {
        // ...
      }
    }

  • 24.3 If the property/method is a , use or .

    boolean
    isVal()
    hasVal()

    // bad
    if (!dragon.age()) {
      return false;
    }
    
    // good
    if (!dragon.hasAge()) {
      return false;
    }

  • 24.4 It’s okay to create and functions, but be consistent.

    get()
    set()

    class Jedi {
      constructor(options = {}) {
        const lightsaber = options.lightsaber || 'blue';
        this.set('lightsaber', lightsaber);
      }
    
      set(key, val) {
        this[key] = val;
      }
    
      get(key) {
        return this[key];
      }
    }

back to top

Events

  • 25.1 When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass an object literal (also known as a "hash") instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:

    // bad
    $(this).trigger('listingUpdated', listing.id);
    
    // ...
    
    $(this).on('listingUpdated', (e, listingID) => {
      // do something with listingID
    });

    prefer:

    // good
    $(this).trigger('listingUpdated', { listingID: listing.id });
    
    // ...
    
    $(this).on('listingUpdated', (e, data) => {
      // do something with data.listingID
    });

back to top

jQuery

  • 26.1 Prefix jQuery object variables with a .

    $

    // bad
    const sidebar = $('.sidebar');
    
    // good
    const $sidebar = $('.sidebar');
    
    // good
    const $sidebarBtn = $('.sidebar-btn');

  • 26.2 Cache jQuery lookups.

    // bad
    function setSidebar() {
      $('.sidebar').hide();
    
      // ...
    
      $('.sidebar').css({
        'background-color': 'pink',
      });
    }
    
    // good
    function setSidebar() {
      const $sidebar = $('.sidebar');
      $sidebar.hide();
    
      // ...
    
      $sidebar.css({
        'background-color': 'pink',
      });
    }

  • 26.3 For DOM queries use Cascading or parent > child . jsPerf
    $('.sidebar ul')
    $('.sidebar > ul')

  • 26.4 Use with scoped jQuery object queries.

    find

    // bad
    $('ul', '.sidebar').hide();
    
    // bad
    $('.sidebar').find('ul').hide();
    
    // good
    $('.sidebar ul').hide();
    
    // good
    $('.sidebar > ul').hide();
    
    // good
    $sidebar.find('ul').hide();

back to top

ECMAScript 5 Compatibility

back to top

ECMAScript 6+ (ES 2015+) Styles

  • 28.1 This is a collection of links to the various ES6+ features.
  1. Arrow Functions
  2. Classes
  3. Object Shorthand
  4. Object Concise
  5. Object Computed Properties
  6. Template Strings
  7. Destructuring
  8. Default Parameters
  9. Rest
  10. Array Spreads
  11. Let and Const
  12. Exponentiation Operator
  13. Iterators and Generators
  14. Modules

  • 28.2 Do not use TC39 proposals that have not reached stage 3.

    Why? They are not finalized, and they are subject to change or to be withdrawn entirely. We want to use JavaScript, and proposals are not JavaScript yet.

back to top

Standard Library

The Standard Library contains utilities that are functionally broken but remain for legacy reasons.

  • 29.1 Use instead of global . eslint:

    no-restricted-globals
    Number.isNaN
    isNaN

    Why? The global coerces non-numbers to numbers, returning true for anything that coerces to NaN. If this behavior is desired, make it explicit.

    isNaN

    // bad
    isNaN('1.2'); // false
    isNaN('1.2.3'); // true
    
    // good
    Number.isNaN('1.2.3'); // false
    Number.isNaN(Number('1.2.3')); // true

  • 29.2 Use instead of global . eslint:

    no-restricted-globals
    Number.isFinite
    isFinite

    Why? The global coerces non-numbers to numbers, returning true for anything that coerces to a finite number. If this behavior is desired, make it explicit.

    isFinite

    // bad
    isFinite('2e3'); // true
    
    // good
    Number.isFinite('2e3'); // false
    Number.isFinite(parseInt('2e3', 10)); // true

back to top

Testing

  • 30.1 Yup.

    function foo() {
      return true;
    }

  • 30.2 No, but seriously:
    • Whichever testing framework you use, you should be writing tests!
    • Strive to write many small pure functions, and minimize where mutations occur.
    • Be cautious about stubs and mocks - they can make your tests more brittle.
    • We primarily use
      mocha
      and
      jest
      at Airbnb.
      tape
      is also used occasionally for small, separate modules.
    • 100% test coverage is a good goal to strive for, even if it’s not always practical to reach it.
    • Whenever you fix a bug, write a regression test. A bug fixed without a regression test is almost certainly going to break again in the future.

back to top

Performance

back to top

Resources

Learning ES6+

Read This

Tools

Other Style Guides

Other Styles

Further Reading

Books

Blogs

Podcasts

back to top

In the Wild

This is a list of organizations that are using this style guide. Send us a pull request and we'll add you to the list.

back to top

Translation

This style guide is also available in other languages:

The JavaScript Style Guide Guide

Chat With Us About JavaScript

Contributors

ライセンス

(MITライセンス)

著作権 (c) 2012 Airbnb

許可は、取得するすべての人に無料で付与されます。 このソフトウェアおよび関連するドキュメント ファイルのコピー ( 「ソフトウェア」)、以下を含む制限なしにソフトウェアを取り扱うこと。 使用、コピー、変更、マージ、公開する権利を制限なく、 本ソフトウェアのコピーを配布、サブライセンス、および/または販売し、 ソフトウェアが提供される人にそうすることを許可します。 次の条件:

上記の著作権表示およびこの許可表示は、 本ソフトウェアのすべてのコピーまたは重要な部分に含まれています。

本ソフトウェアは「現状有姿」で提供され、いかなる種類の保証もありません。 明示または黙示(以下の保証を含むがこれらに限定されない) 商品性、特定目的への適合性、および非侵害。 いかなる場合も、著者または著作権者は、いかなる責任も負わないものとします。 請求、損害、またはその他の責任(契約上の行為であるかどうかにかかわらず)、 不法行為またはその他の方法で、起因、起因、または関連して ソフトウェアまたはソフトウェアの使用またはその他の取引。

一番上に戻る

改正

このガイドをフォークし、チームのスタイルガイドに合わせてルールを変更することをお勧めします。以下に、スタイルガイドの修正点をいくつか挙げることができます。これにより、マージの競合に対処することなく、スタイルガイドを定期的に更新できます。

};