aboutsummaryrefslogtreecommitdiff
path: root/files/uk/web/javascript/reference/global_objects/object/freeze/index.html
blob: 86269bfda1eb773496d3ae2885a6ac0777303fbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
---
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
---
<div>{{JSRef}}</div>

<p>Метод <code><strong>Object.freeze()</strong></code> <strong>заморожує</strong> об'єкт. Заморожений об'єкт не може бути змінений; заморожування запобігає додаванню нових властивостей, видаленню існуючих властивостей, зміні доступності існуючих властивостей для переліку, налаштування та запису, а також зміні значень існуючих властивостей. Також, заморожування об'єкта не дає змінювати його прототип. Метод <code>freeze()</code> повертає той самий об'єкт, що був переданий.</p>

<div>{{EmbedInteractiveExample("pages/js/object-freeze.html")}}</div>



<h2 id="Синтаксис">Синтаксис</h2>

<pre class="syntaxbox"><code>Object.freeze(<var>obj</var>)</code></pre>

<h3 id="Параметри">Параметри</h3>

<dl>
 <dt><code>obj</code></dt>
 <dd>Об'єкт, який потрібно заморозити.</dd>
</dl>

<h3 id="Значення_що_повертається">Значення, що повертається</h3>

<p>Об'єкт, переданий у функцію.</p>

<h2 id="Опис">Опис</h2>

<p>Ніщо не може бути додане чи видалене з набору властивостей замороженого об'єкта. Будь-яка спроба це зробити зазнає невдачі, або непомітно, або з викиданням винятку {{jsxref("TypeError")}} (найчастіше, але не винятково, у {{jsxref("Strict_mode", "строгому режимі", "", 1)}}).</p>

<p>Для властивостей-значень замороженого об'єкта не можна змінювати значення, атрибутам writable та configurable встановлено значення false. Властивості-аксесори (гетери та сетери) працюють, як і раніше (і так само створюють ілюзію, що ви міняєте значення). Зауважте, що значення, які є об'єктами, можна змінювати, якщо тільки вони теж не заморожені. Масив, як об'єкт, може бути заморожений; після цього його елементи не можуть бути змінені, і жоден елемент не може бути доданий чи видалений з масиву.</p>

<p><code>freeze()</code> повертає той самий об'єкт, який був переданий у функцію. Він <em>не створює</em> заморожену копію.</p>

<h2 id="Приклади">Приклади</h2>

<h3 id="Заморожування_обєктів">Заморожування об'єктів</h3>

<pre class="brush: js">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 }
</pre>

<h3 id="Заморожування_масивів">Заморожування масивів</h3>

<pre class="brush: js">let a = [0];
Object.freeze(a); // Тепер масив не можна змінювати.

a[0]=1; // непомітно не спрацьовує
a.push(2); // непомітно не спрацьовує

// У строгому режимі такі спроби викидатимуть TypeError
function fail() {
  "use strict"
  a[0] = 1;
  a.push(2);
}

fail();</pre>

<p>Заморожений об'єкт є <em>незмінним</em>. Однак, він не обов'язково є <em>константою</em>. Наступний приклад демонструє, що заморожений об'єкт не є константою (неглибока заморозка).</p>

<pre class="brush: js">obj1 = {
  internal: {}
};

Object.freeze(obj1);
obj1.internal.a = 'значенняА';

obj1.internal.a // 'значенняА'</pre>

<p>Щоб об'єкт був константою, все дерево посилань (прямі та непрямі посилання на інші об'єкти) має посилатися тільки на незмінні заморожені об'єкти. Заморожений об'єкт називається незмінним, бо <em>стан </em>об'єкта (значення та посилання на інші об'єкти) всередині всього об'єкта є зафіксованим. Зауважте, що рядки, числа та булеві значення завжди незмінні, і що функції та масиви є об'єктами.</p>

<h4 id="Що_таке_неглибока_заморозка">Що таке "неглибока заморозка"?</h4>

<p>Результат виклику <code>Object.freeze(<var>object</var>)</code> стосується лише безпосередніх властивостей об'єкта <code>object</code>, і запобігає додаванню, видаленню чи переприсвоєнню значень властивостей у майбутньому <em>тільки</em> на об'єкті <code>object</code>. Якщо ж значеннями цих властивостей є інші об'єкти, ці об'єкти не заморожуються, і на них можуть здійснюватись операції додавання, видалення чи переприсвоєння значень властивостей.</p>

<pre class="brush: js">var employee = {
  name: "Дмитро",
  designation: "Розробник",
  address: {
    street: "Городоцька",
    city: "Львів"
  }
};

Object.freeze(employee);

employee.name = "Вова"; // непомітно не спрацює у нестрогому режимі
employee.address.city = "Винники"; // атрибути дочірнього об'єкта можна змінювати

console.log(employee.address.city) // Виведе: "Винники"
</pre>

<p>Щоб зробити об'єкт незмінним, рекурсивно заморозьте кожну властивість типу object (глибока заморозка). Застосовуйте свій шаблон для кожного конкретного елементу, коли знаєте, що об'єкт не містить {{interwiki("wikipedia", "Цикл_(теорія_графів)", "циклів")}} у дереві посилань, інакше запуститься нескінченний цикл. Покращенням функції <code>deepFreeze()</code> була б внутрішня функція, яка отримує аргументом шлях (наприклад, масив), щоб можна було заборонити рекурсивний виклик <code>deepFreeze()</code>, коли об'єкт знаходиться у процесі перетворення на незмінний об'єкт. Ви все одно ризикуєте заморозити об'єкт, який не треба заморожувати, наприклад, [window].</p>

<pre class="brush: js">function deepFreeze(object) {

  // Отримати імена властивостей, визначених на об'єкті
  var propNames = Object.getOwnPropertyNames(object);

  // Заморозити властивості перед тим, як заморожувати себе

  for (let name of propNames) {
    let value = object[name];

    object[name] = value &amp;&amp; typeof value === "object" ?
      deepFreeze(value) : value;
  }

  return Object.freeze(object);
}

var obj2 = {
  internal: {
    a: null
  }
};

deepFreeze(obj2);

obj2.internal.a = 'новеЗначення'; // непомітно не спрацює у нестрогому режимі
obj2.internal.a; // null
</pre>

<h2 id="Примітки_щодо_використання">Примітки щодо використання</h2>

<p>У ES5, якщо аргументом цього методу є не об'єкт (примітив), він спричинить помилку {{jsxref("TypeError")}}. У ES2015 аргумент, який не є об'єктом, сприйматиметься як звичайний заморожений об'єкт, і буде просто повернений.</p>

<pre class="brush: js">&gt; Object.freeze(1)
TypeError: 1 is not an object // код ES5

&gt; Object.freeze(1)
1                             // код ES2015
</pre>

<p>Об'єкти {{domxref("ArrayBufferView")}} з елементами спричинять помилку {{jsxref("TypeError")}}, оскільки вони є представленнями ділянок пам'яті, і неодмінно спричинять інші можливі проблеми:</p>

<pre class="brush: js">&gt; Object.freeze(new Uint8Array(0)) // Немає елементів
Uint8Array []

&gt; Object.freeze(new Uint8Array(1)) // Має елементи
TypeError: Cannot freeze array buffer views with elements

&gt; Object.freeze(new DataView(new ArrayBuffer(32))) // Немає елементів
DataView {}

&gt; Object.freeze(new Float64Array(new ArrayBuffer(64), 63, 0)) // Немає елементів
Float64Array []

&gt; Object.freeze(new Float64Array(new ArrayBuffer(64), 32, 2)) // Має елементи
TypeError: Cannot freeze array buffer views with elements
</pre>

<p>Зауважте наступне; оскільки три стандартні властивості (<code>buf.byteLength</code>, <code>buf.byteOffset</code> та <code>buf.buffer</code>) є доступними лише для читання (так само, як у {{jsxref("ArrayBuffer")}} чи у {{jsxref("SharedArrayBuffer")}}), немає причини намагатися заморожувати ці властивості.</p>

<h3 id="Порівняння_з_Object.seal">Порівняння з <code>Object.seal()</code></h3>

<p>Об'єкти, запечатані через {{jsxref("Object.seal()")}}, дозволяють змінювати свої існуючі властивості. Властивості об'єктів, заморожених через <code>Object.freeze()</code>, стають незмінними.</p>

<h2 id="Специфікації">Специфікації</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Специфікація</th>
   <th scope="col">Статус</th>
   <th scope="col">Коментар</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.2.3.9', 'Object.freeze')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td>Початкове визначення. Реалізоване у JavaScript 1.8.5.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-object.freeze', 'Object.freeze')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-object.freeze', 'Object.freeze')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2>



<p>{{Compat("javascript.builtins.Object.freeze")}}</p>

<h2 id="Див._також">Див. також</h2>

<ul>
 <li>{{jsxref("Object.isFrozen()")}}</li>
 <li>{{jsxref("Object.preventExtensions()")}}</li>
 <li>{{jsxref("Object.isExtensible()")}}</li>
 <li>{{jsxref("Object.seal()")}}</li>
 <li>{{jsxref("Object.isSealed()")}}</li>
</ul>