知らなかったでは済まされない!ESLintの「guard-for-in」でプロの技を身につける

2024-04-02

ESLintのRules「guard-for-in」は、for-inループでオブジェクトのプロパティをループする際に、予期せぬ動作を防ぐためのルールです。

問題点

for-inループは、オブジェクト自身のプロパティだけでなく、原型チェーン上のプロパティもループします。これは、意図せずともループに予期せぬプロパティが含まれてしまう可能性があり、バグの原因となる可能性があります。

解決策

guard-for-inルールは、for-inループ内でifステートメントを使用して、ループするプロパティをフィルタリングすることを推奨します。

//  警告が出るコード
for (const key in obj) {
  doSomething(key);
}

//  問題ないコード
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    doSomething(key);
  }
}

上記の例では、最初のコードはobj自身のプロパティだけでなく、原型チェーン上のプロパティもループします。一方、2番目のコードはhasOwnPropertyメソッドを使用して、obj自身のプロパティのみをループしています。

設定

guard-for-inルールは、ESLintの設定ファイルで有効にすることができます。

{
  "rules": {
    "guard-for-in": "error"
  }
}

上記の設定は、for-inループでifステートメントを使用していない場合にエラーを出力します。

補足

  • hasOwnPropertyメソッドは、オブジェクトが指定されたプロパティを持っているかどうかを判断するために使用されます。
  • for-ofループは、for-inループよりも新しいループ構文であり、原型チェーン上のプロパティをループしません。
  • 上記は、guard-for-inルールの概要を説明したものです。詳細は、上記の参考資料を参照してください。
  • guard-for-inルールの有効化は、コードの安全性と信頼性を向上させることができます。


基本的な例

//  警告が出るコード
for (const key in obj) {
  doSomething(key);
}

//  問題ないコード
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    doSomething(key);
  }
}

オブジェクトの所有権を確認する

const obj = {
  foo: "bar",
  baz: "qux"
};

//  警告が出るコード
for (const key in obj) {
  console.log(key); // "foo", "baz", "constructor", ...
}

//  問題ないコード
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key); // "foo", "baz"
  }
}

原型チェーン上のプロパティを無視する

const obj = Object.create(null);
obj.foo = "bar";

//  警告が出るコード
for (const key in obj) {
  console.log(key); // "foo"
}

//  問題ないコード
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key); // ログは出力されない
  }
}

for-ofループを使用する

const obj = {
  foo: "bar",
  baz: "qux"
};

//  問題ないコード
for (const key of Object.keys(obj)) {
  console.log(key); // "foo", "baz"
}
  • hasOwnPropertyメソッドの代わりに、in演算子を使用してオブジェクトの所有権を確認することもできます。
//  問題ないコード
for (const key in obj) {
  if (key in obj) {
    doSomething(key);
  }
}
  • Object.keysメソッドを使用して、オブジェクトの所有プロパティの配列を取得することもできます。
//  問題ないコード
const keys = Object.keys(obj);
for (const key of keys) {
  doSomething(key);
}


guard-for-inルール以外の方法

Object.keysメソッドを使用して、オブジェクトの所有プロパティの配列を取得することができます。この配列をループすることで、原型チェーン上のプロパティを無視することができます。

const obj = {
  foo: "bar",
  baz: "qux"
};

//  問題ないコード
const keys = Object.keys(obj);
for (const key of keys) {
  doSomething(key);
}

for-ofループを使用する

for-ofループは、for-inループよりも新しいループ構文であり、原型チェーン上のプロパティをループしません。

const obj = {
  foo: "bar",
  baz: "qux"
};

//  問題ないコード
for (const key of obj) {
  doSomething(key);
}

オブジェクトの所有権を確認する

hasOwnPropertyメソッドを使用して、オブジェクトが指定されたプロパティを持っているかどうかを判断することができます。

const obj = {
  foo: "bar",
  baz: "qux"
};

//  問題ないコード
for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    doSomething(key);
  }
}
  • in演算子を使用して、オブジェクトの所有権を確認することもできます。
//  問題ないコード
for (const key in obj) {
  if (key in obj) {
    doSomething(key);
  }
}

guard-for-inルール以外にも、for-inループで予期せぬ動作を防ぐための方法はいくつかあります。それぞれの方法のメリットとデメリットを理解し、状況に応じて適切な方法を選択することが重要です。