このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。

View in English Always switch to English

in 演算子

Baseline 広く利用可能

この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2015年7月以降、すべてのブラウザーで利用可能です。

in 演算子は、指定されたプロパティが指定されたオブジェクトにある場合に true を返します。

in演算子は他のコレクション内の値を検索するために使用することはできません。配列内に特定の値が存在するかどうかを検査するには、 Array.prototype.includes() を使用してください。 集合の場合は、 Set.prototype.has() を使用してください。

試してみましょう

const car = { make: "Honda", model: "Accord", year: 1998 };

console.log("make" in car);
// 予想される結果: true

delete car.make;
if ("make" in car === false) {
  car.make = "Suzuki";
}

console.log(car.make);
// 予想される結果: "Suzuki"

構文

js
prop in object
#prop in object

引数

prop

プロパティ名または配列のインデックスを表す文字列式またはシンボルです(シンボルではない場合は、文字列に変換されます)。プライベート要素の識別子である場合もあります。

object

オブジェクト(またはそのプロトタイプチェーン)に、指定された名前 (prop) のプロパティが含まれているかどうかを確認するオブジェクト。

例外

TypeError

object がオブジェクトでない場合(つまり、プリミティブ型の場合)に発生します。

解説

in 演算子は、オブジェクトまたはそのプロトタイプチェーン内に、文字列またはシンボルプロパティが存在するかどうかの検査を行います。継承されていないプロパティのみを調べる場合は、代わりに Object.hasOwn() を使用してください。

オブジェクトにプロパティが存在しても、その値が undefined である場合があります。したがって、 "x" in objobj.x !== undefined とは同等ではありません。プロパティ追加後に infalse を返すようにするには、そのプロパティの値を undefined に設定する代わりに、 delete 演算子を使用してください。

in 演算子を使用して、特定のクラスのプライベートフィールドまたはメソッドがクラスで定義されているかどうかを調べることができます。プロパティが定義されている場合、演算子は true を返し、そうでない場合は false を返します。これは、そのオブジェクトがそのクラスのコンストラクターで作成された場合にのみ true を返すため、「ブランドチェック」と呼ばれています。その後、他のプライベート要素にも安全にアクセスすることができます。

これは特別な構文です。 in 演算子の左辺は式ではなくプロパティ識別子ですが、引用符で囲まれていません(囲むと文字列プロパティとなり、プライベート要素ではなくなるため)。

現在のクラスと無関係なオブジェクトのプライベート要素にアクセスすると、undefinedを返すのではなく TypeError が発生するため、この構文により以下のように短縮できます。

js
class C {
  #x;
  static isC(obj) {
    try {
      obj.#x;
      return true;
    } catch {
      return false;
    }
  }
}

これが次のようになります。

js
class C {
  #x;
  static isC(obj) {
    return #x in obj;
  }
}

また、一般的に、存在しない可能性のあるプライベート要素にアクセスするためだけにエラーを処理する必要性を避けることができます。

ただし、 in 演算子では、プライベート要素を事前に囲みクラスで宣言することが要求されます。そうしないと、宣言されていないプライベート要素にアクセスしようとした場合と同じ SyntaxError ("Private field '#x' must be declared in an enclosing class") が発生します。

js
class C {
  foo() {
    #x in this;
  }
}

new C().foo(); // SyntaxError: Private field '#x' must be declared in an enclosing class

基本的な使い方

次の例で in 演算子の使用法を示します。

js
// 配列
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
0 in trees; // true を返す
3 in trees; // true を返す
6 in trees; // false を返す
"bay" in trees; // false を返す (添字の指す値ではなく、添字の数値を指定しなければならない)
"length" in trees; // true を返す (length は Array のプロパティ)
Symbol.iterator in trees; // true を返す (配列は反復可能。 ES2015 以上で動作する)

// 定義済みオブジェクト
"PI" in Math; // true を返す

// ユーザー定義オブジェクト
const myCar = { make: "Honda", model: "Accord", year: 1998 };
"make" in myCar; // true を返す
"model" in myCar; // true を返す

in 演算子の右側には、オブジェクトを指定しなければなりません。例えば、String コンストラクターで作成した文字列は指定できますが、文字列リテラルは指定できません。

js
const color1 = new String("green");
"length" in color1; // true を返す

const color2 = "coral";
// エラーが発生 (color2 は String オブジェクトではない)
"length" in color2;

削除済みあるいは未定義状態のプロパティへの in の使用

delete 演算子で削除されたプロパティについては、in 演算子は false を返します。

js
const myCar = { make: "Honda", model: "Accord", year: 1998 };
delete myCar.make;
"make" in myCar; // false を返す

const trees = ["redwood", "bay", "cedar", "oak", "maple"];
delete trees[3];
3 in trees; // false を返す

undefined を設定しているが削除されていないプロパティについて、in 演算子は true を返します。

js
const myCar = { make: "Honda", model: "Accord", year: 1998 };
myCar.make = undefined;
"make" in myCar; // true を返す
js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
3 in trees; // true を返す

in 演算子は、空の配列スロットに対して false を返します。直接アクセスしても undefined が返されます。

js
const empties = new Array(3);
empties[2]; // undefined を返す
2 in empties; // false を返す

これを避けるためには、新しい配列が常に空でない値で埋められるようにするか、配列の終わりを超える位置に書き込まないようにしてください。

js
const empties = new Array(3).fill(undefined);
2 in empties; // true を返す

継承されたプロパティ

in 演算子はプロトタイプチェーン内のプロパティに対して true を返します。オブジェクトを任意のキーと値の組を格納するために使用している場合、これは望ましくない可能性があります。

js
const ages = { alice: 18, bob: 27 };

function hasPerson(name) {
  return name in ages;
}

hasPerson("hasOwnProperty"); // true

オブジェクトにキーを保有している場合を調べるには、 Object.hasOwn() を使用することができます。

js
const ages = { alice: 18, bob: 27 };

function hasPerson(name) {
  return Object.hasOwn(ages, name);
}

hasPerson("hasOwnProperty"); // false

あるいは、その他のバグを避けるために、 null プロトタイプオブジェクトまたは Map を使用して ages を格納することを検討してください。

js
const ages = new Map([
  ["alice", 18],
  ["bob", 27],
]);

function hasPerson(name) {
  return ages.has(name);
}

hasPerson("hasOwnProperty"); // false

in 演算子を使用したブランドチェックの実装

下記のコード断片は、オブジェクトが Person コンストラクターで作成されたかを指示する静的関数を示しています。これにより、他のメソッドを安全に実行することができるかどうかを確認できます。

js
class Person {
  #age;
  constructor(age) {
    this.#age = age;
  }
  static isPerson(o) {
    return #age in o;
  }
  ageDifference(other) {
    return this.#age - other.#age;
  }
}

const p1 = new Person(20);
const p2 = new Person(30);
console.log(p1.ageDifference(p2)); // -10
console.log(Person.isPerson(p1)); // true

if (Person.isPerson(p1) && Person.isPerson(p2)) {
  console.log(p1.ageDifference(p2)); // -10
}

これは、次のケースを防ぐのに役立ちます。

js
const p2 = {};

p1.ageDifference(p2); // TypeError: Cannot read private member #age from an object whose class did not declare it

in 演算子を使わずに、オブジェクトがプライベート要素をもってかどうかを調べるには、 try...catch ブロックを使用する必要があります。

また、これをクラスの [Symbol.hasInstance]() メソッドとして実装することもできます。これにより、 instanceof 演算子を使用して同じチェックを実行できます(既定では、オブジェクトのプロトタイプチェーン内の Person.prototype の存在のみを調べます)。

js
class Person {
  #age;
  constructor(age) {
    this.#age = age;
  }
  static [Symbol.hasInstance](o) {
    // Testing `this` to prevent false-positives when
    // calling `instanceof SubclassOfPerson`
    return this === Person && #age in o;
  }
  ageDifference(other) {
    return this.#age - other.#age;
  }
}

const p1 = new Person(20);
const p2 = new Person(30);

if (p1 instanceof Person && p2 instanceof Person) {
  console.log(p1.ageDifference(p2)); // -10
}

これ以外の例は、プライベート要素クラスガイドを参照してください。

仕様書

仕様書
ECMAScript® 2027 Language Specification
# sec-relational-operators

ブラウザーの互換性

関連情報