in

Operator

Der <code>in</code>-Operator liefert <code>true</code>, wenn die angegebene Eigenschaft im Objekt oder seiner prototype chain vorhanden ist.

seit JavaScript ES3 – Baseline: alle Browser Kategorie: syntax

Signatur

prop in object

Beschreibung

Der in-Operator liefert true, wenn die angegebene Eigenschaft im angegebenen Objekt oder seiner prototype chain enthalten ist.

Der in-Operator kann nicht dazu verwendet werden, in anderen Collections nach Werten zu suchen. Um zu prüfen, ob ein bestimmter Wert in einem Array existiert, verwende Array.prototype.includes(). Für Sets verwende Set.prototype.has().

Der in-Operator prüft, ob eine string- oder symbol-Eigenschaft in einem Objekt oder seiner prototype chain vorhanden ist. Wenn du nur nach nicht geerbten Eigenschaften prüfen möchtest, verwende stattdessen Object.hasOwn().

Eine Eigenschaft kann in einem Objekt vorhanden sein, aber den Wert undefined haben. Daher ist "x" in obj nicht dasselbe wie obj.x !== undefined. Damit in nach dem Hinzufügen einer Eigenschaft false zurückgibt, verwende den delete-Operator, anstatt den Wert der Eigenschaft auf undefined zu setzen.

Du kannst den in-Operator auch verwenden, um zu prüfen, ob ein bestimmtes privates Klassenfeld oder eine private Methode in einem Objekt definiert wurde. Der Operator liefert true, wenn die Eigenschaft definiert ist, andernfalls false. Dies wird als branded check bezeichnet, weil er genau dann true zurückgibt, wenn das Objekt mit diesem Klassen-constructor erzeugt wurde, wonach du auch sicher auf andere private Elemente zugreifen kannst.

Dies ist eine spezielle Syntax — die linke Seite des in-Operators ist ein Property-Identifier statt einer Expression, aber ohne Anführungszeichen (weil es sonst eine string-Eigenschaft wäre und kein privates Element).

Da der Zugriff auf private Elemente auf Objekten, die nicht zur aktuellen Klasse gehören, einen TypeError wirft, anstatt undefined zurückzugeben, erlaubt diese Syntax, folgendes zu verkürzen:

Sie vermeidet außerdem generell die Notwendigkeit, sich mit Error-Handling zu befassen, nur um auf ein möglicherweise nicht vorhandenes privates Element zuzugreifen.

Allerdings erfordert der in-Operator dennoch, dass das private Element zuvor in der umschließenden Klasse deklariert wurde — andernfalls würde er einen SyntaxError werfen ("Private field '#x' must be declared in an enclosing class"), denselben wie beim Versuch, auf ein nicht deklariertes privates Element zuzugreifen.

Parameter

Name Typ Default Beschreibung
$prop Pflicht string | symbol Ein string oder symbol, der einen Property-Namen repräsentiert (Nicht-Symbole werden zu Strings gecoerct). Kann auch ein Private-Element-Identifier sein.
$object Pflicht Object Objekt, bei dem geprüft wird, ob es (oder seine prototype chain) die Eigenschaft mit dem angegebenen Namen (prop) enthält.

Rückgabewert

Typ
boolean
Beschreibung
true, wenn die angegebene Eigenschaft im Objekt oder seiner prototype chain vorhanden ist, sonst false.

Beispiele

Grundlegende Verwendung

// Arrays
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
0 in trees; // returns true
3 in trees; // returns true
6 in trees; // returns false
"bay" in trees; // returns false (you must specify the index number, not the value at that index)
"length" in trees; // returns true (length is an Array property)
Symbol.iterator in trees; // returns true

// Predefined objects
"PI" in Math; // returns true

// Custom objects
const myCar = { make: "Honda", model: "Accord", year: 1998 };
"make" in myCar; // returns true
"model" in myCar; // returns true

Objekt auf der rechten Seite erforderlich

const color1 = new String("green");
"length" in color1; // returns true

const color2 = "coral";
// generates an error (color2 is not a String object)
"length" in color2;

Verwendung von in mit gelöschten oder undefined-Eigenschaften

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

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

Auf undefined gesetzte Eigenschaft

const myCar = { make: "Honda", model: "Accord", year: 1998 };
myCar.make = undefined;
"make" in myCar; // returns true

Array-Element auf undefined gesetzt

const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
3 in trees; // returns true

Leere Array-Slots

const empties = new Array(3);
empties[2]; // returns undefined
2 in empties; // returns false

Array mit Werten füllen

const empties = new Array(3).fill(undefined);
2 in empties; // returns true

Geerbte Eigenschaften

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

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

hasPerson("hasOwnProperty"); // true

Object.hasOwn() verwenden

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

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

hasPerson("hasOwnProperty"); // false

Map als Alternative

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

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

hasPerson("hasOwnProperty"); // false

in-Operator für branded checks

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
}

Fehlerfall ohne branded check

const p2 = {};

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

Branded check via Symbol.hasInstance

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
}

try/catch-Verkürzung mit in

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

Kurzform mit in

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

SyntaxError bei nicht deklariertem privatem Feld

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

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

// Wichtig · Fallstricke

Wirft einen TypeError, wenn object kein Objekt ist (d. h. ein Primitive). Der in-Operator mit privaten Element-Identifiern erfordert, dass das private Element in der umschließenden Klasse deklariert ist, sonst wird ein SyntaxError geworfen.