Оператор in
Оператор in у JavaScript перевіряє, чи існує вказана властивість в об'єкті або індекс у масиві. Це один із базових операторів, який часто розуміють неправильно: він дивиться на наявність ключа, а не на його значення, і враховує весь ланцюжок прототипів.
Теорія
TL;DR
- Синтаксис:
propName in object, результат завждиtrueабоfalse. - Перевіряє наявність ключа, а не значення:
'a' in { a: undefined }даєtrue. - Працює з об'єктами, масивами та функціями; індекси масиву це звичайні ключі.
- Враховує прототип:
'toString' in {}даєtrue. - Тільки власні властивості перевіряють через
Object.hasOwn(obj, key)абоobj.hasOwnProperty(key). - Якщо праворуч не об'єкт (
null,undefined, число, рядок), будеTypeError.
Швидкий приклад
const user = { name: 'Alice', age: 25 };
console.log('name' in user); // true
console.log('email' in user); // false
console.log('toString' in user); // true (успадковано)
console.log(Object.hasOwn(user, 'toString')); // false (не власна властивість)Синтаксис
propName in objectДе:
propNameце рядок (або вираз, який приводиться до рядка чи символа),objectце об'єкт, масив або інша структура з ключами.
Число ліворуч теж допустиме: воно буде приведене до рядка, тому 0 in arr насправді перевіряє ключ '0'.
Робота з об'єктами
const user = {
name: 'Alice',
age: 25
};
console.log('name' in user); // true
console.log('age' in user); // true
console.log('email' in user); // falseОператор
inповертаєtrue, якщо властивість існує в об'єкті, навіть коли її значення дорівнюєundefined.
Саме в цьому головна особливість:
const obj = { a: undefined };
console.log('a' in obj); // true
console.log(obj.a === undefined); // trueТобто
inперевіряє наявність ключа, а не значення. Порівнянняobj.a === undefinedне дозволяє відрізнити «ключа немає» від «ключ є, але значення undefined», аinдозволяє.
Робота з масивами
const arr = ['a', 'b', 'c'];
console.log(0 in arr); // true, індекс 0 існує
console.log(2 in arr); // true, індекс 2 існує
console.log(3 in arr); // false, такого індексу немаєJavaScript сприймає індекси масиву як звичайні властивості:
arr[0]еквівалентнеarr['0'].
Через це in бачить «дірки» у розріджених масивах: у ['a', , 'c'] вираз 1 in arr дасть false, хоча arr.length дорівнює 3.
Успадкування через прототип
Оператор in перевіряє не лише власні властивості, а й успадковані через прототип.
const person = { name: 'Alice' };
console.log('toString' in person); // true, бо успадковано від Object.prototypeЩоб перевірити тільки власні властивості, використовуйте
Object.hasOwn(person, 'key')або старішийperson.hasOwnProperty('key'):javascriptperson.hasOwnProperty('toString'); // false person.hasOwnProperty('name'); // true
Те саме працює і з класами:
class User {
constructor() {
this.name = 'Alex';
}
}
User.prototype.age = 25;
const u = new User();
console.log('name' in u); // true (власна властивість)
console.log('age' in u); // true (успадковано від прототипу)Помилка при використанні з не-об'єктом
Якщо права частина не є об'єктом і не може бути до нього приведена, JavaScript викине помилку:
'length' in null; // TypeError
'length' in undefined; // TypeError
'length' in 'text'; // TypeError (примітив, а не об'єкт)Тому перед перевіркою переконайтеся, що змінна не
nullі неundefined, наприклад черезobj && 'key' in obj.
Підсумок
| Питання | Відповідь |
|---|---|
| Що перевіряє | Наявність ключа (властивості або індексу) |
| Працює з | Об'єктами, масивами, функціями |
| Що повертає | true / false |
| Чи враховує прототип | Так |
| Чи перевіряє значення | Ні |
Приклади для порівняння:
| Перевірка | Результат | Пояснення |
|---|---|---|
'name' in { name: 'Alice' } | true | ключ існує |
'email' in { name: 'Alice' } | false | ключа немає |
0 in ['a', 'b'] | true | індекс 0 є |
2 in ['a', 'b'] | false | індексу 2 немає |
'toString' in {} | true | успадковано від Object.prototype |
Типові помилки
- Очікувати, що
inперевіряє значення. Ключ зі значеннямundefinedабоnullусе одно даєtrue. - Забувати про прототип:
'constructor' in objі'toString' in objзавждиtrueдля звичайного об'єкта. - Використовувати
inдля пошуку елемента в масиві.'b' in ['a','b']даєfalse, бо перевіряються індекси; для значень потрібенarr.includes('b'). - Викликати
inнаnullчиundefinedі отримуватиTypeErrorзамістьfalse. - Плутати
inзfor...inта зinstanceof: це різні конструкції, попри схожі назви. - Викликати
obj.hasOwnProperty(key)на об'єкті, створеному черезObject.create(null); такий об'єкт не має цього методу, тому безпечнішеObject.hasOwn(obj, key).
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.