Spec-Zone.ru › JavaScript

in

Базовый уровень Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

Оператор in возвращает true, если указанное свойство находится в указанном объекте или его цепочке прототипов.

Оператор in не может использоваться для поиска значений в других коллекциях. Чтобы проверить, существует ли определенное значение в массиве, используйте Array.prototype.includes(). Для наборов (Set) используйте Set.prototype.has().

Попробовать

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

console.log("make" in car);
// Expected output: true

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

console.log(car.make);
// Expected output: "Suzuki"

Синтаксис

prop in object
#prop in object

Параметры

prop
Строка или символ, представляющий имя свойства (не-символы будут приведены к строкам). Также может быть идентификатором приватного элемента.
object
Объект, который проверяется на наличие свойства с указанным именем (prop) в нем (или в его цепочке прототипов).

Исключения

TypeError
Выбрасывается, если object не является объектом (т.е. примитивом).

Описание

Оператор in проверяет, присутствует ли строковое или символьное свойство в объекте или его цепочке прототипов. Если вы хотите проверить только неунаследованные свойства, используйте Object.hasOwn() вместо этого.

Свойство может присутствовать в объекте, но иметь значение undefined. Следовательно, "x" in obj не то же самое, что obj.x !== undefined. Чтобы заставить in возвращать false после добавления свойства, используйте оператор delete вместо того, чтобы устанавливать значение этого свойства в undefined.

Вы также можете использовать оператор in для проверки того, был ли определен конкретный приватный член класса или метод в объекте. Оператор возвращает true, если свойство определено, и false в противном случае. Это известно как брендовая проверка (branded check), потому что он возвращает true только в том случае, если объект был создан с помощью этого конструктора класса, после чего вы также можете безопасно получить доступ к другим приватным элементам.

Это специальный синтаксис — левая часть оператора in является идентификатором свойства вместо выражения, но без кавычек (поскольку в противном случае это строковое свойство, а не приватный элемент).

Поскольку доступ к приватным элементам объектов, не связанных с текущим классом, вызывает TypeError вместо возврата undefined, этот синтаксис позволяет сократить:

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

До:

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

Это также обычно позволяет избежать необходимости обработки ошибок только для доступа к приватному элементу, который может не существовать.

Однако оператор in по-прежнему требует, чтобы приватный элемент был объявлен заранее в заключающем классе — в противном случае будет выброшено исключение SyntaxError ("Private field '#x' must be declared in an enclosing class"), то же самое, что и при попытке доступа к необъявленному приватному элементу.

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

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

Примеры

Основное использование

Следующие примеры показывают некоторые варианты использования оператора in.

// 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

Вы должны указать объект с правой стороны оператора in. Например, вы можете указать строку, созданную с помощью конструктора String, но вы не можете указать строковый литерал.

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;

Использование оператора in с удаленными или неопределенными свойствами

Если вы удаляете свойство с помощью оператора delete, оператор in возвращает false для этого свойства.

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

Если вы устанавливаете свойство в undefined, но не удаляете его, оператор in возвращает true для этого свойства.

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

Оператор in вернет false для пустых ячеек массива, даже если прямой доступ к нему возвращает undefined.

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

Чтобы избежать этого, убедитесь, что новый массив всегда заполнен непустыми значениями или что вы не записываете данные по индексам, выходящим за пределы массива.

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

Унаследованные свойства

Оператор in возвращает true для свойств в цепочке прототипов. Это может быть нежелательно, если вы используете объекты для хранения произвольных пар ключ-значение.

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

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

hasPerson("hasOwnProperty"); // true

Вы можете использовать Object.hasOwn() для проверки наличия ключа в объекте.

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

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

hasPerson("hasOwnProperty"); // false

В качестве альтернативы, вам следует рассмотреть возможность использования объекта с нулевым прототипом или Map для хранения ages, чтобы избежать других ошибок.

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

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

hasPerson("hasOwnProperty"); // false

Использование оператора in для реализации брендовых проверок

Фрагмент кода ниже демонстрирует статическую функцию, которая определяет, был ли объект создан с помощью конструктора Person и, следовательно, может безопасно выполнять другие методы.

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
}

Это помогает предотвратить следующий случай:

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 в цепочке прототипов объекта).

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
# sec-relational-operators

Совместимость с браузерами

Десктопные Мобильные Серверные
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
in
1
12
1
4
1
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0

См. также

  • for...in
  • delete
  • Object.hasOwn()
  • Reflect.has()
  • Перечисляемость и принадлежность свойств

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API