--- title: Object.freeze() slug: Web/JavaScript/Reference/Global_Objects/Object/freeze tags: - ECMAScript 5 - JavaScript - Object - freeze - Об'єкт - заморожування - метод translation_of: Web/JavaScript/Reference/Global_Objects/Object/freeze ---
Метод Object.freeze()
заморожує об'єкт. Заморожений об'єкт не може бути змінений; заморожування запобігає додаванню нових властивостей, видаленню існуючих властивостей, зміні доступності існуючих властивостей для переліку, налаштування та запису, а також зміні значень існуючих властивостей. Також, заморожування об'єкта не дає змінювати його прототип. Метод freeze()
повертає той самий об'єкт, що був переданий.
Object.freeze(obj)
obj
Об'єкт, переданий у функцію.
Ніщо не може бути додане чи видалене з набору властивостей замороженого об'єкта. Будь-яка спроба це зробити зазнає невдачі, або непомітно, або з викиданням винятку {{jsxref("TypeError")}} (найчастіше, але не винятково, у {{jsxref("Strict_mode", "строгому режимі", "", 1)}}).
Для властивостей-значень замороженого об'єкта не можна змінювати значення, атрибутам writable та configurable встановлено значення false. Властивості-аксесори (гетери та сетери) працюють, як і раніше (і так само створюють ілюзію, що ви міняєте значення). Зауважте, що значення, які є об'єктами, можна змінювати, якщо тільки вони теж не заморожені. Масив, як об'єкт, може бути заморожений; після цього його елементи не можуть бути змінені, і жоден елемент не може бути доданий чи видалений з масиву.
freeze()
повертає той самий об'єкт, який був переданий у функцію. Він не створює заморожену копію.
var obj = { prop: function() {}, foo: 'ква' }; // До заморожування: можна додавати нові властивості, // а також змінювати чи видаляти існуючі властивості obj.foo = 'мяв'; obj.lumpy = 'гав'; delete obj.prop; // Заморожуємо. var o = Object.freeze(obj); // Повертається той самий об'єкт, який ми передали. o === obj; // true // Об'єкт заморожено. Object.isFrozen(obj); // === true // Тепер будь-які зміни не працюють obj.foo = 'му'; // нічого не робить // непомітно не додає властивість obj.quaxxor = 'весела качка'; // У строгому режимі такі спроби викинуть винятки TypeError function fail(){ 'use strict'; obj.foo = 'бум'; // викидає TypeError delete obj.foo; // викидає TypeError delete obj.quaxxor; // повертає true, бо атрибут 'quaxxor' не був доданий obj.sparky = 'фух'; // викидає TypeError } fail(); // Спроба внести зміни через Object.defineProperty; // обидві інструкції викинуть TypeError. Object.defineProperty(obj, 'ohai', { value: 17 }); Object.defineProperty(obj, 'foo', { value: 'уф' }); // Також неможливо змінити прототип // обидві наведені інструкції викинуть TypeError. Object.setPrototypeOf(obj, { x: 20 }) obj.__proto__ = { x: 20 }
let a = [0]; Object.freeze(a); // Тепер масив не можна змінювати. a[0]=1; // непомітно не спрацьовує a.push(2); // непомітно не спрацьовує // У строгому режимі такі спроби викидатимуть TypeError function fail() { "use strict" a[0] = 1; a.push(2); } fail();
Заморожений об'єкт є незмінним. Однак, він не обов'язково є константою. Наступний приклад демонструє, що заморожений об'єкт не є константою (неглибока заморозка).
obj1 = { internal: {} }; Object.freeze(obj1); obj1.internal.a = 'значенняА'; obj1.internal.a // 'значенняА'
Щоб об'єкт був константою, все дерево посилань (прямі та непрямі посилання на інші об'єкти) має посилатися тільки на незмінні заморожені об'єкти. Заморожений об'єкт називається незмінним, бо стан об'єкта (значення та посилання на інші об'єкти) всередині всього об'єкта є зафіксованим. Зауважте, що рядки, числа та булеві значення завжди незмінні, і що функції та масиви є об'єктами.
Результат виклику Object.freeze(object)
стосується лише безпосередніх властивостей об'єкта object
, і запобігає додаванню, видаленню чи переприсвоєнню значень властивостей у майбутньому тільки на об'єкті object
. Якщо ж значеннями цих властивостей є інші об'єкти, ці об'єкти не заморожуються, і на них можуть здійснюватись операції додавання, видалення чи переприсвоєння значень властивостей.
var employee = { name: "Дмитро", designation: "Розробник", address: { street: "Городоцька", city: "Львів" } }; Object.freeze(employee); employee.name = "Вова"; // непомітно не спрацює у нестрогому режимі employee.address.city = "Винники"; // атрибути дочірнього об'єкта можна змінювати console.log(employee.address.city) // Виведе: "Винники"
Щоб зробити об'єкт незмінним, рекурсивно заморозьте кожну властивість типу object (глибока заморозка). Застосовуйте свій шаблон для кожного конкретного елементу, коли знаєте, що об'єкт не містить {{interwiki("wikipedia", "Цикл_(теорія_графів)", "циклів")}} у дереві посилань, інакше запуститься нескінченний цикл. Покращенням функції deepFreeze()
була б внутрішня функція, яка отримує аргументом шлях (наприклад, масив), щоб можна було заборонити рекурсивний виклик deepFreeze()
, коли об'єкт знаходиться у процесі перетворення на незмінний об'єкт. Ви все одно ризикуєте заморозити об'єкт, який не треба заморожувати, наприклад, [window].
function deepFreeze(object) { // Отримати імена властивостей, визначених на об'єкті var propNames = Object.getOwnPropertyNames(object); // Заморозити властивості перед тим, як заморожувати себе for (let name of propNames) { let value = object[name]; object[name] = value && typeof value === "object" ? deepFreeze(value) : value; } return Object.freeze(object); } var obj2 = { internal: { a: null } }; deepFreeze(obj2); obj2.internal.a = 'новеЗначення'; // непомітно не спрацює у нестрогому режимі obj2.internal.a; // null
У ES5, якщо аргументом цього методу є не об'єкт (примітив), він спричинить помилку {{jsxref("TypeError")}}. У ES2015 аргумент, який не є об'єктом, сприйматиметься як звичайний заморожений об'єкт, і буде просто повернений.
> Object.freeze(1) TypeError: 1 is not an object // код ES5 > Object.freeze(1) 1 // код ES2015
Об'єкти {{domxref("ArrayBufferView")}} з елементами спричинять помилку {{jsxref("TypeError")}}, оскільки вони є представленнями ділянок пам'яті, і неодмінно спричинять інші можливі проблеми:
> Object.freeze(new Uint8Array(0)) // Немає елементів Uint8Array [] > Object.freeze(new Uint8Array(1)) // Має елементи TypeError: Cannot freeze array buffer views with elements > Object.freeze(new DataView(new ArrayBuffer(32))) // Немає елементів DataView {} > Object.freeze(new Float64Array(new ArrayBuffer(64), 63, 0)) // Немає елементів Float64Array [] > Object.freeze(new Float64Array(new ArrayBuffer(64), 32, 2)) // Має елементи TypeError: Cannot freeze array buffer views with elements
Зауважте наступне; оскільки три стандартні властивості (buf.byteLength
, buf.byteOffset
та buf.buffer
) є доступними лише для читання (так само, як у {{jsxref("ArrayBuffer")}} чи у {{jsxref("SharedArrayBuffer")}}), немає причини намагатися заморожувати ці властивості.
Object.seal()
Об'єкти, запечатані через {{jsxref("Object.seal()")}}, дозволяють змінювати свої існуючі властивості. Властивості об'єктів, заморожених через Object.freeze()
, стають незмінними.
Специфікація | Статус | Коментар |
---|---|---|
{{SpecName('ES5.1', '#sec-15.2.3.9', 'Object.freeze')}} | {{Spec2('ES5.1')}} | Початкове визначення. Реалізоване у JavaScript 1.8.5. |
{{SpecName('ES6', '#sec-object.freeze', 'Object.freeze')}} | {{Spec2('ES6')}} | |
{{SpecName('ESDraft', '#sec-object.freeze', 'Object.freeze')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.builtins.Object.freeze")}}