きれいな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 のユーザーとロールの管理原則と使用方法の詳細

推薦する

Mysql は、デッドロック問題を解決するために kill コマンドを使用します (実行中の特定の SQL ステートメントを強制終了します)。

MySQL を使用して特定のステートメントを実行すると、データ量が多いためにデッドロックが発生し、...

Vueのスロットの詳細な説明

Vue でのコードの再利用により、mixnis が提供されます。テンプレートの再利用により、スロット...

MySQL データ挿入効率の比較

データを挿入するとき、以前オフィス システムに取り組んでいたときにはデータベースのパフォーマンスにつ...

CSS ラベルモード表示プロパティの詳細な説明

コードは次のようになります。 <!DOCTYPE html> <html> ...

Dockerイメージ作成の完全なプロセス

目次序文作成手順CentOSベースイメージを作成するコンテナを作成してカスタマイズするカスタムコンテ...

インデックスは MySQL クエリ条件で使用されますか?

雇用主から MySQL クエリ条件でインデックスが使用されるかどうかを尋ねられた場合、どのように答え...

iostat を使用して Linux ハードディスクの IO パフォーマンスを表示する方法

TOP 観察: IO 待機に占められる CPU 時間の割合。30% を超えると、IO の負荷が高くな...

MySQL における varchar 型と char 型の違い

目次前述のVARCHAR型VARCHAR適用可能な状況CHAR型テストVARCHAR(5)とVARC...

MySQL 5.7.16 のインストールと設定方法のグラフィック チュートリアル (Ubuntu 16.04)

Ubuntu 16.04 に MySQL 5.7 をインストールするにはどうすればいいですか?メイ...

Vue Element Sortablejs を使用してテーブル列をドラッグする詳細な説明

1. css: ドラッグテーブル.css @charset "UTF-8"; ....

Linux スケジュールタスクの関連操作の概要

皆様の参考と操作を容易にするために、様々な主要ウェブサイトを検索し、関連するスケジュールされたタスク...

CSS3 で @media を使用して Web ページの適応を実現するためのサンプル コード

現在、コンピュータモニターの画面解像度はますます高くなる傾向にありますが、携帯電話などのモバイルデバ...

Linuxでawkを使用する方法の詳細な説明

awk を学ぶ前に、sed、grep、tr、cut などのコマンドを学んでおく必要があります。これら...

MySQL 8.0 ウィンドウ関数の紹介と概要

序文MySQL 8.0 より前は、Oracle、SQL SERVER、PostgreSQL などの他...

時間のかかるDockerエラーのトラブルシューティングプロセス記録

目次起源環境情報トラブルシューティングのプロセス要約する起源顧客は CentOS をベースにしたカス...