Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Прапорці writable, enumerable, configurable». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`writable`, `enumerable` і `configurable` це три службові прапорці дескриптора властивості (property descriptor), які керують поведінкою властивостей об'єкта.** `writable` дозволяє змінювати значення, `enumerable` робить властивість видимою під час перебору (`for...in`, `Object.keys`, `JSON.stringify`), а `configurable` дозволяє видалити властивість і змінювати самі прапорці. Під час звичайного присвоєння всі три дорівнюють `true`, а під час створення через `Object.defineProperty` за замовчуванням `false`. ```javascript const user = {}; Object.defineProperty(user, 'id', { value: 10, enumerable: true }); user.id = 42; // не змінюється: writable: false console.log(Object.keys(user)); // ['id'] delete user.id; // не видаляється: configurable: false ``` **Ключове:** прочитати прапорці можна через `Object.getOwnPropertyDescriptor(obj, key)`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Прапорці `writable`, `enumerable` і `configurable` це три службові параметри в дескрипторі властивості (property descriptor), які керують поведінкою властивостей об'єктів у JavaScript.** Під час звичайної роботи з об'єктом вони непомітні, але саме вони визначають, чи можна властивість змінити, видалити або перерахувати. ## Теорія ### TL;DR | Прапорець | Що робить | За замовчуванням | | --- | --- | --- | | `writable` | Дозволяє змінювати значення властивості | `false` (якщо властивість створено через `defineProperty`) | | `enumerable` | Робить властивість видимою під час перебору (`for...in`, `Object.keys`) | `false` | | `configurable` | Дозволяє видаляти властивість і змінювати її прапорці | `false` | - Звичайне присвоєння `obj.key = value` створює властивість з усіма прапорцями `true`. - Прочитати прапорці можна через `Object.getOwnPropertyDescriptor(obj, key)`. - Задати їх можна лише через `Object.defineProperty(obj, key, descriptor)`. ### Швидкий приклад ```javascript const user = {}; Object.defineProperty(user, 'name', { value: 'Alice', writable: false, // не можна змінювати enumerable: false, // не з'являється в циклах configurable: false // не можна видалити або змінити прапорці }); console.log(user.name); // "Alice" user.name = 'Bob'; // не змінюється delete user.name; // не видаляється console.log(Object.keys(user)); // [] бо властивість не перераховується ``` ### writable: чи можна змінювати значення ```javascript const user = {}; Object.defineProperty(user, 'age', { value: 25, writable: false }); user.age = 30; // не спрацює console.log(user.age); // 25 ``` - `writable: true` дозволяє змінювати значення; - `writable: false` робить властивість **лише для читання**. У нестрогому режимі запис у таку властивість просто мовчки ігнорується, у strict mode кидається `TypeError`. ### enumerable: чи показувати властивість під час перебору ```javascript const user = {}; Object.defineProperty(user, 'secret', { value: '12345', enumerable: false }); console.log(user.secret); // доступно напряму console.log(Object.keys(user)); // [] бо властивість не видно for (const key in user) console.log(key); // нічого не виведе ``` - `enumerable: true` робить властивість видимою у `for...in`, `Object.keys()`, `JSON.stringify()`; - `enumerable: false` робить її «прихованою». Приклад з реального життя: вбудовані методи (`toString`, `valueOf`) мають `enumerable: false`, щоб не заважати під час перебору. ### configurable: чи можна видалити або змінити прапорці ```javascript const user = {}; Object.defineProperty(user, 'id', { value: 10, configurable: false }); delete user.id; // не видалиться console.log(user.id); // 10 // Спробуємо змінити writable: Object.defineProperty(user, 'id', { writable: true }); // TypeError: Cannot redefine property: id ``` - `configurable: true` дозволяє видалити властивість або змінити її прапорці; - `configurable: false` забороняє видалення і зміну `enumerable`, `configurable` та перехід `writable` з `false` на `true`. > Єдине, що ще можна змінити у такої властивості, це `writable` з `true` на `false`, але не навпаки. ### Як прочитати і як задати прапорці Прочитати: ```javascript const obj = { name: 'Alice' }; const descriptor = Object.getOwnPropertyDescriptor(obj, 'name'); console.log(descriptor); ``` Виведе: ```javascript { value: 'Alice', writable: true, enumerable: true, configurable: true } ``` Задати: ```javascript Object.defineProperty(obj, 'prop', { value: 42, writable: false, enumerable: true, configurable: false }); ``` Підсумок: | Прапорець | Призначення | Приклад | | --- | --- | --- | | `writable` | Чи можна змінювати значення властивості | `user.age = 30` | | `enumerable` | Чи видно властивість під час перебору | `Object.keys(user)` | | `configurable` | Чи можна видалити або перевизначити властивість | `delete user.prop` | ### Типові помилки - **Забувати, що `defineProperty` ставить усі прапорці у `false`.** Властивість, створена без явного `enumerable: true`, зникає з `Object.keys()` і з результату `JSON.stringify()`. - **Чекати на помилку від запису у `writable: false`.** Без `'use strict'` присвоєння мовчки не спрацьовує, і баг помічають пізно. - **Плутати `writable: false` з незмінністю об'єкта.** Якщо у властивості лежить об'єкт, його поля все одно можна змінювати; глибока заморозка це вже `Object.freeze` по всьому дереву. - **Розраховувати повернути `configurable` у `true`.** Це незворотна операція, тому спершу продумують, які властивості справді треба «запечатати». - **Вважати, що `enumerable: false` приховує дані.** Властивість і далі читається напряму і видима для `Object.getOwnPropertyNames()` та `Reflect.ownKeys()`. - **Використовувати спред або `Object.assign` для копіювання.** Вони переносять лише перераховувані власні властивості і втрачають прапорці; для точної копії потрібні `Object.getOwnPropertyDescriptors` і `Object.defineProperties`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.