Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Оператор in». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Оператор `in` перевіряє, чи існує вказана властивість в об'єкті або індекс у масиві, і повертає `true` або `false`.** Він дивиться саме на наявність ключа, а не на значення: `'a' in { a: undefined }` дає `true`. Пошук іде і власними властивостями, і всім ланцюжком прототипів, тому `'toString' in {}` теж `true`. Для перевірки лише власних ключів беруть `Object.hasOwn(obj, key)` або `obj.hasOwnProperty(key)`. ```javascript const user = { name: 'Alice', email: undefined }; 'name' in user; // true 'email' in user; // true (ключ є, хоч значення undefined) 'phone' in user; // false 'toString' in user; // true (успадковано від Object.prototype) ``` **Ключове:** `in` відповідає на питання «чи є такий ключ», а не «чи є в ньому значення», і враховує прототип.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Оператор `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`. ### Швидкий приклад ```javascript 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 (не власна властивість) ``` ### Синтаксис ```javascript propName in object ``` Де: - `propName` це рядок (або вираз, який приводиться до рядка чи символа), - `object` це об'єкт, масив або інша структура з ключами. Число ліворуч теж допустиме: воно буде приведене до рядка, тому `0 in arr` насправді перевіряє ключ `'0'`. ### Робота з об'єктами ```javascript 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`. Саме в цьому головна особливість: ```javascript const obj = { a: undefined }; console.log('a' in obj); // true console.log(obj.a === undefined); // true ``` > Тобто `in` перевіряє наявність ключа, а не значення. Порівняння `obj.a === undefined` не дозволяє відрізнити «ключа немає» від «ключ є, але значення undefined», а `in` дозволяє. ### Робота з масивами ```javascript 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` перевіряє не лише власні властивості, а й успадковані через прототип. ```javascript const person = { name: 'Alice' }; console.log('toString' in person); // true, бо успадковано від Object.prototype ``` > Щоб перевірити тільки власні властивості, використовуйте `Object.hasOwn(person, 'key')` або старіший `person.hasOwnProperty('key')`: > > ```javascript > person.hasOwnProperty('toString'); // false > person.hasOwnProperty('name'); // true > ``` Те саме працює і з класами: ```javascript 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 викине помилку: ```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)`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.