きれいなJavaScriptコードの書き方を教える記事

きれいなJavaScriptコードの書き方を教える記事

クリーンなコードは、読みやすく、再利用しやすく、リファクタリングしやすくなります。日々の仕事では、自分のためだけにコードを書いているわけではないので、きれいなコードを書くことは非常に重要です。実際には、コードを理解、編集、構築する必要がある同僚のグループも考慮する必要があります。

1. 変数

意味のある名前を使う

変数名は説明的で意味のあるものにする必要があります。JavaScript 変数は、camelCase を使用して名前を付ける必要があります。

// しないでください❌
const foo = "[email protected]";
const バー = "ジョン";
定数年齢 = 23;
定数qux = true;

// ✅を実行します
const メールアドレス = "[email protected]";
const firstName = "ジョン";
定数年齢 = 23;
定数isActive = true

ブール変数は、次のような特定の質問に答えるためによく必要になります。

アクティブ
購読しました
リンクされたアカウント

不必要なコンテキストを追加しないようにする

オブジェクトまたはクラスにすでに命名コンテキストが含まれている場合は、変数名に冗長なコンテキストを追加しないでください。

// しないでください❌
定数ユーザー = {
  ユーザーID: "296e2589-7b33-400a-b762-007b730c8e6d",
  ユーザーメール: "[email protected]",
  ユーザー名: "ジョン",
  ユーザ名: "Doe",
  ユーザー年齢: 23,
};

ユーザー.ユーザーID;

// ✅を実行します
定数ユーザー = {
  id: "296e2589-7b33-400a-b762-007b730c8e6d",
  メールアドレス: "[email protected]",
  ファーストネーム: "ジョン",
  姓: "Doe",
  年齢: 23歳
};

ユーザーID;

ハードコードされた値を避ける

定数値を直接挿入するのではなく、意味のある検索可能な定数を宣言するようにしてください。グローバル定数は、SCREAMING_SNAKE_CASE スタイルを使用して名前を付けることができます。

// しないでください❌
タイムアウトを設定します(セッションデータをクリアします、900000);

// ✅を実行します
定数SESSION_DURATION_MS = 15 * 60 * 1000;

タイムアウトを設定します(セッションデータをクリアし、SESSION_DURATION_MS);

2. 機能

意味のある名前を使う

関数名は長い場合でも、関数が実際に何を行うかを説明する必要があります。関数名には通常動詞が使用されますが、ブール値を返す関数は例外になる場合があります。これは、はい/いいえの質問形式になる可能性があり、関数名もキャメルケースにする必要があります。

// しないでください❌
関数トグル() {
  // ...
}

関数は同意しました(ユーザー) {
  // ...
}

// ✅を実行します
関数トグルテーマスイッチャー() {
  // ...
}

関数didAgreeToAllTerms(ユーザー) {
  // ...
}

デフォルトパラメータの使用

デフォルト パラメーターは、&& || や関数本体内で追加の条件を使用するよりも簡潔です。

// しないでください❌
関数 printAllFilesInDirectory(dir) {
  const ディレクトリ = dir || "./";
  // ...
}

// ✅を実行します
関数 printAllFilesInDirectory(dir = "./") {
  // ...
}

パラメータの数を制限する

このルールは議論の余地があるかもしれませんが、パラメータが 3 つ以下の関数を使用するのが最適です。パラメータが多数ある場合は、次の 2 つの状況のいずれかが考えられます。

  • この関数は機能が多すぎるため、分割する必要があります。
  • 何らかの形で関連する関数に渡されるデータは、特殊なデータ構造として渡すことができます。
// しないでください❌
関数 sendPushNotification(タイトル、メッセージ、画像、isSilent、delayMs) {
  // ...
}

sendPushNotification("新しいメッセージ", "...", "http://...", false, 1000);

// ✅を実行します
関数 sendPushNotification({ タイトル、メッセージ、画像、isSilent、delayMs }) {
  // ...
}

定数通知設定 = {
  タイトル:「新しいメッセージ」、
  メッセージ: "..."、
  画像: "http://...",
  isSilent: false、
  遅延時間: 1000,
};

プッシュ通知を送信します(通知設定);

1つの機能で多くのことを行わないようにする

関数は一度に 1 つの処理を実行する必要があります。これにより、関数のサイズと複雑さが軽減され、テスト、デバッグ、リファクタリングが容易になります。

/ しないでください❌
関数pingUsers(ユーザー) {
  users.forEach((ユーザー) => {
    定数userRecord = database.lookup(user);
    if (!userRecord.isActive()) {
      ping(ユーザー);
    }
  });
}

// ✅を実行します
関数 pingInactiveUsers(ユーザー) {
  users.filter(!isUserActive).forEach(ping);
}

関数 isUserActive(ユーザー) {
  定数userRecord = database.lookup(user);
  userRecord.isActive() を返します。
}

ブールフラグをパラメータとして使用しないでください

パラメータとしてブールフラグを持つ関数は、関数を簡略化できることを意味します。

// しないでください❌
関数createFile(name, isPublic) {
  パブリックの場合
    fs.create(`./public/${name}`);
  } それ以外 {
    fs.create(名前);
  }
}

// ✅を実行します
関数createFile(名前) {
  fs.create(名前);
}

関数createPublicFile(名前) {
  ファイルを作成します(`./public/${name}`);
}

重複したコードを書かないようにする

重複したコードを記述すると、ロジックが変更されるたびに複数の場所を変更する必要があります。

// しないでください❌
関数 renderCarsList(車) {
  cars.forEach((車) => {
    const 価格 = car.getPrice();
    車を作る
    const ブランド = car.getBrand();
    const nbOfDoors = car.getNbOfDoors();

    render({ 価格, メーカー, ブランド, ドアの数 });
  });
}

関数 renderMotorcyclesList(オートバイ) {
  オートバイ.forEach((オートバイ) => {
    価格 = オートバイ.getPrice();
    定数 make = オートバイ.getMake();
    const ブランド = オートバイ.getBrand();
    シートの高さを取得します。

    render({ 価格, メーカー, ブランド, ドアの数 });
  });
}

// ✅を実行します
関数 renderVehiclesList(車両) {
  車両.forEach((車両) => {
    定数価格 = 車両.getPrice();
    定数 make = 車両.getMake();
    const ブランド = 車両.getBrand();

    const data = { 価格、メーカー、ブランド };

    スイッチ(車両タイプ){
      ケース「車」:
        data.nbOfDoors = 車両.getNbOfDoors();
        壊す;
      「オートバイ」の場合:
        車両シートの高さを取得します。
        壊す;
    }

    レンダリング(データ);
  });
}

副作用を避ける

JavaScript では、命令型パラダイムよりも関数型パラダイムを優先する必要があります。言い換えれば、ほとんどの場合、関数を純粋に保つ必要があります。副作用により共有状態やリソースが変更され、予期しない問題が発生する可能性があります。すべての副作用は集中管理する必要があります。たとえば、グローバル変数を変更したり、ファイルを変更したりする必要がある場合は、これを実行するためのユーティリティを特別に作成できます。

// しないでください❌
日付を "21-8-2021" とします。

関数splitIntoDayMonthYear() {
  日付 = date.split("-");
}

日月年に分割します();

// 別の関数では日付を文字列として受け取る可能性があります
console.log(日付); // ['21', '8', '2021'];

// ✅を実行します
関数splitIntoDayMonthYear(日付) {
  date.split("-"); を返します。
}

定数日付 = "21-8-2021";
日付を分割します。

// 元の値はそのままです
console.log(日付); // '21-8-2021';
console.log(newDate); // ['21', '8', '2021'];

また、変更可能な値を関数に渡す場合は、値を変更するのではなく、常に値を複製して返す必要があります。

// しないでください❌
関数enrollStudentInCourse(コース, 学生) {
  course.push({ 学生、登録日: Date.now() });
}

// ✅を実行します
関数enrollStudentInCourse(コース, 学生) {
  [...course, { student, enrollmentDate: Date.now() }] を返します。
}

3. 条件文

非負の条件の使用

// しないでください❌
関数 isUserNotVerified(ユーザー) {
  // ...
}

if (!isUserNotVerified(ユーザー)) {
  // ...
}

// ✅を実行します
関数 isUserVerified(ユーザー) {
  // ...
}

if (isUserVerified(ユーザー)) {
  // ...
}

可能な限り略語を使用する

// しないでください❌
if (isActive === true) {
  // ...
}

firstName !== "" && firstName !== null && firstName !== 未定義の場合 {
  // ...
}

const isUserEligible = user.isVerified() && user.didSubscribe() ? true : false;

// ✅を実行します
if (isActive) {
  // ...
}

if (!!firstName) {
  // ...
}

const isUserEligible = user.isVerified() && user.didSubscribe();

分岐が多すぎるのは避ける

早期に返すと、コードはより直線的になり、読みやすくなり、複雑さが軽減されます。

// しないでください❌
関数 addUserService(db, user) {
  もし(!db){
    db.isConnected() の場合 {
      if (!ユーザー) {
        db.insert("users", user) を返します。
      } それ以外 {
        新しいエラーをスローします("ユーザーがいません");
      }
    } それ以外 {
      新しいエラーをスローします("データベース接続がありません");
    }
  } それ以外 {
    新しいエラーをスローします("データベースがありません");
  }
}

// ✅を実行します
関数 addUserService(db, user) {
  if (!db) throw new Error("データベースがありません");
  if (!db.isConnected()) throw new Error("データベース接続がありません");
  if (!user) throw new Error("ユーザーがいません");

  db.insert("users", user) を返します。
}

switch文よりもmap文を優先する

複雑さを軽減し、パフォーマンスを向上させることができます。

// しないでください❌
const getColorByStatus = (ステータス) => {
  スイッチ(ステータス){
    ケース「成功」:
      「緑」を返します。
    ケース「失敗」:
      「赤」を返します。
    ケース「警告」:
      「黄色」を返します。
    ケース「ロード中」:
    デフォルト:
      「青」を返します。
  }
};

// ✅を実行します
const ステータスカラー = {
  成功:「緑」、
  失敗:「赤」、
  警告:「黄色」、
  読み込み中: "青",
};

const getColorByStatus = (status) => statusColors[status] || "青";

オプションチェーンの使用

定数ユーザー = {
  メールアドレス: "[email protected]",
  請求する:
    イバン語: "...",
    スウィフト: "...",
    住所:
      street: "通りの名前",
      州:「CA」、
    },
  },
};

// しないでください❌
const email = (user && user.email) || "該当なし";
定数ストリート =
  (ユーザー&&
    ユーザー.請求 &&
    ユーザー.請求先住所 &&
    ユーザー請求先住所ストリート) ||
  「該当なし」;
定数状態 =
  (ユーザー&&
    ユーザー.請求 &&
    ユーザー.請求先住所 &&
    ユーザー請求先住所州) ||
  「該当なし」;

// ✅を実行します
const email = user?.email ?? "N/A";
const street = user?.billing?.address?.street ?? "N/A";
const street = user?.billing?.address?.state ?? "N/A";

4. 同時実行性

コールバックを避ける

コールバックは混乱を招き、コードが深くネストされてしまう可能性があります。コールバックの代わりに Promise を使用してください。

// しないでください❌
getUser(関数(err, user) {
  getProfile(ユーザー、関数(err、プロファイル) {
    getAccount(プロファイル、関数(err、アカウント) {
      getReports(アカウント、関数(err、レポート) {
        sendStatistics(レポート、関数(err) {
          コンソールエラー(err);
        });
      });
    });
  });
});

// ✅を実行します
ユーザー取得()
  .then(プロファイルを取得)
  .then(アカウントを取得)
  .then(レポートを取得)
  .then(統計を送信)
  .catch((err) => console.error(err));

// または Async/Await を使用する ✅✅

非同期関数sendUserStatistics() {
  試す {
    const user = getUser() を待機します。
    const プロファイル = getProfile(user) を待機します。
    const アカウント = getAccount(profile) を待機します。
    const レポート = getReports(アカウント) を待機します。
    sendStatistics(レポート)を返します。
  } キャッチ (e) {
    コンソールエラー(err);
  }
}

5. エラー処理

スローされたエラーと拒否されたプロミスの処理

/ しないでください❌
試す {
  // 誤りの可能性があるコード
} キャッチ (e) {
  コンソールログ(e);
}

// ✅を実行します
試す {
  // 誤りの可能性があるコード
} キャッチ (e) {
  // 最も適切なもの(またはすべて)に従ってください:
  // 1- console.log よりも適している
  コンソールエラー(e);

  // 2- 該当する場合はユーザーに通知する
  アラートユーザーエラー(e);

  // 3- サーバーに報告
  エラーをサーバに報告します(e);

  // 4- カスタムエラーハンドラを使用する
  新しい CustomError(e) をスローします。
}

6. 注釈

ビジネスロジックのみコメント

読みやすいコードであれば、過剰なコメントを避けることができるため、複雑なロジックのみにコメントする必要があります。

// しないでください❌
関数generateHash(str) {
  // ハッシュ変数
  ハッシュを 0 にします。

  // 文字列の長さを取得します
  length = str.length;とします。

  // 文字列が空の場合は戻り値
  長さが等しい場合
    ハッシュを返します。
  }

  // 文字列内のすべての文字をループします
  (i = 0; i < 長さ; i++) の場合 {
    // 文字コードを取得します。
    char を str.charCodeAt(i) に格納します。

    // ハッシュを作成する
    ハッシュ = (ハッシュ << 5) - ハッシュ + 文字;

    // 32ビット整数に変換
    ハッシュ &= ハッシュ;
  }
}

// ✅を実行します
関数generateHash(str) {
  ハッシュを 0 にします。
  length = str.length;とします。
  長さが等しい場合
    ハッシュを返します。
  }

  (i = 0; i < 長さ; i++) の場合 {
    char を str.charCodeAt(i) に格納します。
    ハッシュ = (ハッシュ << 5) - ハッシュ + 文字;
    hash = hash & hash; // 32ビット整数に変換
  }
  ハッシュを返します。
}

バージョン管理を使用する

コード内に過去のバージョンに関するコメントを残す必要はありません。確認したい場合は、git log を使用して検索するだけです。 。

// しないでください❌
/**
 * 2021-7-21: コーナーケースを修正
 * 2021-7-15: パフォーマンスの改善
 * 2021-7-10: 複数のユーザータイプに対応
 */
関数generateCanonicalLink(user) {
  // 定数セッション = getUserSession(ユーザー)
  定数セッション = user.getSession();
  // ...
}

// ✅を実行します
関数generateCanonicalLink(user) {
  定数セッション = user.getSession();
  // ...
}

さあ、美しいコードを書いてください! 🌈

要約する

クリーンな JavaScript コードの書き方に関するこの記事はこれで終わりです。クリーンな JavaScript コードの書き方についてさらに詳しく知りたい場合は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JSポップアップウィンドウコード集(詳細配置)
  • メールアドレスを検証するための本物の正規表現jsコードの詳細な説明
  • 現在のタイムスタンプを取得するための JavaScript コード
  • JS クラスのカプセル化と実装コード
  • 非常に優れたJSページング効果コード。研究する価値がある
  • ボタンをクリックしたときに60秒のカウントダウンを実現するjsコード
  • JavaScript に関数または変数が存在するかどうかを判定する
  • JavaScript における変数の昇格と関数の昇格の詳細な説明

<<:  Ubuntuで顔認識ログインを実装するための完全な手順

>>:  MySQL 8.0 のユーザーとロールの管理原則と使用方法の詳細

推薦する

複数クリックを防ぐVueの実践

通常、クリック イベントは、メッセージ リマインダーのさまざまな状況に分割されます。これらが処理され...

JS配列の次元削減のいくつかの方法の詳細な説明

2次元配列の次元削減配列インスタンスメソッド concat と ES6 スプレッド演算子を使用した次...

Vue+Websocketはチャット機能を実装するだけです

この記事では、チャット機能を簡単に実装するためのVue+Websocketの具体的なコードを参考まで...

Node.js でのブレークポイント再開の実装

序文通常のビジネスニーズ: 写真、Excel などをアップロードします。結局のところ、数 MB のサ...

LinuxはNetworkManagerを使用してMACアドレスをランダムに生成します

今では、自宅のソファーに座っていても、外の喫茶店にいても、ノートパソコンの電源を入れてWi-Fiに接...

Dockerプライベートライブラリの実装

プライベート Docker レジストリのインストールとデプロイは、Docker テクノロジーを導入、...

docker リモート API のワンクリック TLS 暗号化の実装

目次1. Docker の 2375 ポートを別のポートに変更します。これは一時的な対策にすぎません...

Linux および CentOS (サーバー) に zip および unzip コマンド機能をインストールする

Linux に zip 解凍機能をインストールする通常、 zip コマンドは Linux サーバーに...

MySQL でストアド プロシージャを作成し、データ テーブルに新しいフィールドを追加する方法の分析

この記事では、例を使用して、MySQL でストアド プロシージャを作成し、データ テーブルに新しいフ...

mysqlを使用して、URLから返されたhttp GETリクエストデータを記録します。

ビジネスシナリオの要件と実装ロジックの分析ビジネスでは、HTTP GET を使用してデータを要求する...

Linux を使用して時間指定ファイルが占有するディスク容量を計算する方法

スケジュールされたタスク エディターを開きます。Cent は、デフォルトで vim を使用して直接開...

Nginx サーバーの https 設定方法の例

Linux: Linux バージョン 3.10.0-123.9.3.el7.x86_64 ngin...

CSS3 ボタン境界アニメーションの実装

まず効果を見てみましょう: html <a href="#"> &l...

HTMLページ間でパラメータを渡すフロントエンド方式の詳細な説明

プロジェクトでよくある状況として、案件リストなどのリストが存在することがあります。リスト内の項目をク...

Linux で g++ を使用してプログラムをコンパイルする際の -I (大文字の i)、-L (大文字の l)、-l (小文字の l) の機能の詳細な説明

初心者の Linux ユーザーとして、私は単純なgcc/g++操作を何度も使用してきましたが、少し複...