プログラミングスタイル

この章では、ES6 の新しい構文をコーディングの実践に適用し、それを従来の JavaScript 構文と組み合わせて、合理的で読みやすく保守しやすいコードを作成する方法について説明します。

多くの企業や組織がスタイル仕様を公開しています。以下の内容は主に Airbnb の JavaScript スタイル仕様について言及しています。

ブロックレベルのスコープ

(1)let は var を置き換えます

ES6 では、変数を宣言するための 2 つの新しいコマンド、letconst が導入されました。このうち、let は、var を完全に置き換えることができます。これは、2 つのセマンティクスが同じであり、let には副作用がないためです。

'厳密を使用';

if (true) {
  x = 'こんにちは' とします。
}

for (i = 0; i < 10; i++) {
  コンソール.ログ(i);
}

上記のコードで「let」の代わりに「var」を使用すると、実際には 2 つのグローバル変数が宣言されますが、これは明らかに意図したものではありません。変数は、それが宣言されているコード ブロック内でのみ有効である必要があります。var コマンドではこれを行うことはできません。

var コマンドには変数の昇格効果がありますが、 let コマンドにはこの問題がありません。

'厳密を使用';

if (true) {
  console.log(x); // 参照エラー
  x = 'こんにちは' とします。
}

上記のコードで let の代わりに var が使用されている場合、変数宣言がコード ブロックの先頭に昇格されるため、console.log 行はエラーを報告しませんが、unknown を出力します。これは、変数が最初に宣言され、後で使用されるという原則に違反します。

したがって、「var」コマンドを使用せず、代わりに「let」コマンドを使用することをお勧めします。

(2)グローバル定数とスレッドセーフ

letconst の間では、最初に const を使用することをお勧めします。特にグローバル環境では、変数を設定せず、定数のみを設定する必要があります。

いくつかの理由から、constlet よりも好まれます。 1 つは、「const」がプログラムを読む人に、この変数は変更すべきではないことを思い出させることができるということです。もう 1 つは、「const」は関数型プログラミングの考え方に沿ったものであり、その演算は値を変更するだけであるということです。新しい値が作成され、これは将来の分散操作にも有益です。最後の理由は、JavaScript コンパイラーが const を最適化するため、より多くの const を使用すると、プログラムの実行効率が向上します。 letconst の本質的な違いは、実際にはコンパイラ内で異なる方法で処理されることです。

// 悪い
var a = 1、b = 2、c = 3;

// 良い
定数 a = 1;
定数 b = 2;
const c = 3;

// 最高
const [a, b, c] = [1, 2, 3];

「const」を使用して定数を宣言することには、2 つの利点もあります。1 つは、コードを読む人が値を変更すべきではないことにすぐに気づくことです。2 つ目は、変数値を不用意に変更することによって発生するエラーを防ぐことです。

すべての関数は定数に設定する必要があります。

長期的には、JavaScript はマルチスレッド実装になる可能性があります (Intel の River Trail のようなプロジェクトなど)。現時点では、「let」で表される変数は、マルチスレッド コードではなく、シングル スレッド コードでのみ使用される必要があります。これはスレッドの安全性を確保するのに役立ちます。

静的文字列では常に一重引用符またはバッククォーテーションを使用しますが、二重引用符は使用しません。動的文字列ではバッククォートが使用されます。

// 悪い
const a = "フーバー";
const b = 'foo' + a + 'bar';

// 許容できる
const c = `foobar`;

// 良い
const a = 'foobar';
const b = `foo${a}bar`;

代入の構造化

配列メンバーを使用して変数に値を代入する場合は、分割代入が推奨されます。

const arr = [1, 2, 3, 4];

// 悪い
const first = arr[0];
const 秒 = arr[1];

// 良い
const [最初、2 番目] = arr;

関数パラメータがオブジェクトのメンバーである場合は、構造化代入が推奨されます。

// 悪い
関数 getFullName(user) {
  const firstName = ユーザー.firstName;
  const lastName = user.lastName;
}

// 良い
関数 getFullName(obj) {
  const { 名、姓 } = obj;
}

// 最高
関数 getFullName({ 名, 姓 }) {
}

関数が複数の値を返す場合、配列分割代入よりもオブジェクト分割代入が優先して使用されます。これにより、後で戻り値を追加したり、戻り値の順序を変更したりすることが容易になります。

// 悪い
関数 processInput(入力) {
  return [左、右、上、下];
}

// 良い
関数 processInput(入力) {
  return { 左、右、上、下 };
}

const {左、右} = processInput(入力);

物体

オブジェクトが 1 行で定義されている場合、最後のメンバーはカンマで終わりません。複数行で定義されたオブジェクトの場合、最後のメンバーはカンマで終わります。

// 悪い
const a = { k1: v1, k2: v2, };
const b = {
  k1: v1、
  k2:v2
};

// 良い
const a = { k1: v1, k2: v2 };
const b = {
  k1: v1、
  k2: v2、
};

オブジェクトはできる限り静的である必要があり、一度定義すると、新しい属性を自由に追加することはできません。属性の追加が避けられない場合は、Object.assign メソッドを使用します。

// 悪い
const a = {};
a.x = 3;

// 形状変更が避けられない場合
const a = {};
Object.assign(a, { x: 3 });

// 良い
const a = { x: null };
a.x = 3;

オブジェクトの属性名が動的である場合は、オブジェクトの作成時に属性式を使用して定義できます。

// 悪い
const obj = {
  ID:5、
  名前: 「サンフランシスコ」、
};
obj[getKey('enabled')] = true;

// 良い
const obj = {
  ID:5、
  名前: 「サンフランシスコ」、
  [getKey('enabled')]: true、
};

上記のコードでは、オブジェクト「obj」の最後の属性名を計算する必要があります。現時点では、属性式を使用し、新しい obj を作成するときにこの属性を他の属性と一緒に定義するのが最善です。このようにして、すべてのプロパティが 1 か所で定義されます。

さらに、オブジェクトのプロパティとメソッドは、記述しやすくするために、できるだけ簡潔に表現する必要があります。

var ref = '何らかの値';

// 悪い
const アトム = {
  参照: 参照、

  値: 1addValue: 関数 (値) {
    アトム値 + 値を返します。
  }、
};

// 良い
const アトム = {
  参照、

  値: 1addValue() {
    アトム値 + 値を返します。
  }、
};

配列

配列をコピーするには、スプレッド演算子 (...) を使用します。

// 悪い
const len = items.length;
const itemsCopy = [];
させてください。

for (i = 0; i < len; i++) {
  アイテムコピー[i] = アイテム[i];
}

// 良い
const itemsCopy = [...items];

Array.from メソッドを使用して、配列のようなオブジェクトを配列に変換します。

const foo = document.querySelectorAll('.foo');
const ノード = Array.from(foo);

関数

即時実行関数はアロー関数の形式で記述できます。

(() => {
  console.log('インターネットへようこそ');
})();

匿名関数がパラメータとして使用される状況では、代わりにアロー関数を使用してみてください。これはより簡潔であり、これを拘束するためです。

// 悪い
[1, 2, 3].map(関数 (x) {
  x * x を返します。
});

// 良い
[1, 2, 3].map((x) => {
  x * x を返します。
});

// 最高
[1, 2, 3].map(x => x * x);

アロー関数は Function.prototype.bind を置き換え、this をバインドするために self/_this/that を使用すべきではなくなりました。

// 悪い
const self = this;
constboundMethod = function(...params) {
  return メソッド.apply(self, params);
}

// 許容できる
constboundMethod = method.bind(this);

// 最高
constboundMethod = (...params) => method.apply(this, params);

シンプルで単一行の再利用不可能な関数の場合は、アロー関数を使用することをお勧めします。関数本体が複雑で行数が多い場合は、従来の関数記述方法を使用する必要があります。

すべての設定項目は 1 つのオブジェクトに集中し、最後のパラメータとして配置する必要があります。コードのセマンティクスが低下し、他の設定項目を追加するのに役立たないため、ブール値をパラメータとして直接使用しないことをお勧めします。未来。

// 悪い
関数除算(a, b, オプション = false ) {
}

// 良い
function Division(a, b, { オプション = false } = {}) {
}

関数本体内で引数変数を使用せず、代わりに残り演算子 (...) を使用してください。 REST 演算子は引数を取得することを明示的に示しており、引数は配列のようなオブジェクトであるため、REST 演算子は実数の配列を提供できます。

// 悪い
関数 concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  戻り args.join('');
}

// 良い
function concatenateAll(...args) {
  戻り args.join('');
}

デフォルト値構文を使用して、関数パラメータのデフォルト値を設定します。

// 悪い
関数 handleThings(opts) {
  オプト = オプト {};
}

// 良い
関数 handleThings(opts = {}) {
  // ...
}

マップ構造

オブジェクトとマップの違いに注意してください。オブジェクトは、現実世界のエンティティ オブジェクトをシミュレートする場合にのみ使用してください。 「key: value」データ構造だけが必要な場合は、Map 構造を使用します。 Map にはトラバーサル メカニズムが組み込まれているためです。

let map = new Map(arr);

for (map.keys() のキーを許可) {
  コンソール.ログ(キー);
}

for (map.values() の値を許可) {
  console.log(値);
}

for (map.entries() の let 項目) {
  console.log(アイテム[0], アイテム[1]);
}

クラス

プロトタイプを必要とする操作ではなく、常にクラスを使用してください。 Class がより簡潔に書かれており、理解しやすいためです。

// 悪い
関数キュー(コンテンツ = []) {
  this._queue = [...コンテンツ];
}
Queue.prototype.pop = function() {
  const 値 = this._queue[0];
  this._queue.splice(0, 1);
  戻り値;
}

// 良い
クラスキュー{
  コンストラクター(コンテンツ = []) {
    this._queue = [...コンテンツ];
  }
  ポップ() {
    const 値 = this._queue[0];
    this._queue.splice(0, 1);
    戻り値;
  }
}

extends を使用して継承を実装すると、より簡単であり、instanceof 操作を中断する危険がないためです。

// 悪い
const 継承 = require('inherits');
関数 PeekableQueue(コンテンツ) {
  Queue.apply(this, 内容);
}
継承(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
  this._queue[0] を返します。
}

// 良い
class PeekableQueue extends Queue {
  ピーク() {
    this._queue[0] を返します。
  }
}

モジュール

ES6 モジュール構文は、JavaScript モジュールを記述する標準的な方法であり、Node.js の CommonJS 構文を置き換えるためにこの記述方法を使用することを主張します。

まず、「require()」の代わりに「import」を使用します。

// CommonJSの書き方
const moduleA = require('moduleA');
const func1 = モジュールA.func1;
const func2 = モジュールA.func2;

// ES6の書き方
import { func1, func2 } から 'moduleA';

2 番目に、「module.exports」の代わりに「export」を使用します。

// commonJSの書き方
var React = require('react');

var ブレッドクラム = React.createClass({
  与える() {
    <nav /> を返します。
  }
});

module.exports = ブレッドクラム;

// ES6の書き方
「react」から React をインポートします。

class Breadcrumbs extends React.Component {
  与える() {
    <nav /> を返します。
  }
};

デフォルトのブレッドクラムをエクスポートします。

モジュールに出力値が 1 つしかない場合は、「exportdefault」を使用します。モジュールに複数の出力値がある場合、出力値の 1 つが特に重要でない限り、「exportdefault」を使用しないことをお勧めします。出力値は等しいため、export default と通常の export を同時に使用しないでください。

モジュールがデフォルトで関数をエクスポートする場合、関数名の最初の文字はユーティリティ メソッドであることを示すために小文字にする必要があります。

関数 makeStyleGuide() {
}

デフォルトの makeStyleGuide をエクスポートします。

モジュールがデフォルトでオブジェクトを出力する場合、それが構成値オブジェクトであることを示すために、オブジェクト名の最初の文字を大文字にする必要があります。

const スタイルガイド = {
  es6: {
  }
};

デフォルトのスタイルガイドをエクスポートします。

ESLint の使用法

ESLint は、構文規則とコーディング スタイルのチェック ツールであり、正しい構文と統一されたスタイルのコードが記述されていることを確認するために使用できます。

まず、ESLint をプロジェクトのルート ディレクトリにインストールします。

$ npm install --save-dev eslint

次に、Airbnb 構文ルール、インポート、a11y、および React プラグインをインストールします。

$ npm install --save-dev eslint-config-airbnb
$ npm install --save-dev eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react

最後に、プロジェクトのルート ディレクトリに新しい .eslintrc ファイルを作成して、ESLint を構成します。

{
  "拡張": "eslint-config-airbnb"
}

現在のプロジェクトのコードが事前に設定されたルールに準拠しているかどうかを確認できるようになりました。

「index.js」ファイルのコードは以下のとおりです。

var used = '目的がない!';

関数greet() {
    var message = 'Hello, World!';
    console.log(メッセージ);
}

挨拶する();

ESLint を使用してこのファイルをチェックすると、エラーが報告されます。

$ npx eslint インデックス.js
インデックス.js
  1:1 エラー 予期しない変数です。代わりに let または const を使用してください no-var
  1:5 エラーの未使用が定義されていますが、使用されていません no-unused-vars
  4:5 エラー 2 文字のインデントが予期されましたが、4 つのインデントが見つかりました
  4:5 エラー 予期しない変数です。変数なしの代わりに let または const を使用してください
  5:5 エラー 2 文字のインデントが予期されましたが、4 つのインデントが見つかりました

✖ 5 件の問題 (エラー 5 件、警告 0 件)

上記のコードは、元のファイルに 5 つのエラーがあることを示しています。そのうちの 2 つは、var コマンドを使用すべきではないというものですが、1 つは、変数が定義されているが使用されていないというものです。他の 2 つは行の先頭にあります。インデントは、指定された 2 つのスペースではなく、4 つのスペースです。


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0