Поверхностная и глубокая заморозка
Разберитесь, насколько глубоко распространяется заморозка.
«Поверхностная и глубокая заморозка» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.
Заморозка действует поверхностно
Object.freeze блокирует только верхний уровень объекта. Любой вложенный объект или массив, на который он ссылается, остаётся полностью изменяемым.
Это удивляет многих разработчиков и приводит к трудно обнаружимым ошибкам.
Доказательство поверхностного ограничения
Заморозьте объект с вложенным объектом. Верхний уровень будет заблокирован, но вложенный объект всё ещё можно изменить.
const user = Object.freeze({
name: 'Ada',
address: { city: 'London' }
});
user.name = 'Grace';
user.address.city = 'Paris';
console.log(user.name);
console.log(user.address.city);Вложенные массивы тоже
Массивы внутри замороженного объекта также не защищены. Можно вызывать push и pop, а также переназначать их элементы.
const state = Object.freeze({ tags: ['a', 'b'] });
state.tags.push('c');
state.tags[0] = 'X';
console.log(state.tags);isFrozen подтверждает это
Вложенный объект сообщает для isFrozen значение false, подтверждая, что заморозка не распространилась внутрь.
const obj = Object.freeze({ inner: { v: 1 } });
console.log(Object.isFrozen(obj));
console.log(Object.isFrozen(obj.inner));Написание deepFreeze
Чтобы заблокировать всё, используйте рекурсию: заморозьте объект, а затем заморозьте каждое вложенное свойство-объект. Это называется глубокой заморозкой.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const value = obj[key];
if (value && typeof value === 'object') {
deepFreeze(value);
}
}
return Object.freeze(obj);
}
const data = deepFreeze({ a: { b: { c: 1 } } });
data.a.b.c = 999;
console.log(data.a.b.c);deepFreeze для массивов
Массивы тоже являются объектами, поэтому та же рекурсия замораживает и их. После этого добавление элементов и записи в элементы блокируются на каждом уровне вложенности.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const value = obj[key];
if (value && typeof value === 'object') deepFreeze(value);
}
return Object.freeze(obj);
}
const state = deepFreeze({ list: [1, 2, 3] });
state.list.push(4);
state.list[0] = 99;
console.log(state.list);Проверка глубокой заморозки
После глубокой заморозки каждый вложенный объект сообщает для isFrozen значение true.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const v = obj[key];
if (v && typeof v === 'object') deepFreeze(v);
}
return Object.freeze(obj);
}
const o = deepFreeze({ a: { b: 1 } });
console.log(Object.isFrozen(o));
console.log(Object.isFrozen(o.a));Защита от циклов
Если объект ссылается на самого себя, наивная рекурсия зациклится навсегда. Пропускайте уже замороженные объекты, чтобы обеспечить безопасность.
function deepFreeze(obj) {
if (Object.isFrozen(obj)) return obj;
for (const key of Object.keys(obj)) {
const v = obj[key];
if (v && typeof v === 'object') deepFreeze(v);
}
return Object.freeze(obj);
}
const a = { name: 'a' };
a.self = a;
deepFreeze(a);
console.log(Object.isFrozen(a.self));Цена глубокой заморозки
Глубокая заморозка посещает каждое вложенное значение, что требует времени и памяти для больших структур. Замораживайте только то, что действительно нуждается в защите, например общую config или константы.
function deepFreeze(obj) {
if (Object.isFrozen(obj)) return obj;
Object.keys(obj).forEach(k => {
const v = obj[k];
if (v && typeof v === 'object') deepFreeze(v);
});
return Object.freeze(obj);
}
const small = deepFreeze({ a: 1, b: { c: 2 } });
console.log('frozen deeply:', Object.isFrozen(small.b));Когда поверхностной заморозки достаточно
Если объект содержит только примитивы, поверхностный вызов Object.freeze уже полностью его защищает. Глубокая заморозка нужна только при наличии вложенных объектов или массивов.
const flat = Object.freeze({ a: 1, b: 'two', c: true });
flat.a = 100;
console.log(flat.a);
console.log(Object.isFrozen(flat));Почему это важно
Понимание различия между поверхностной и глубокой заморозкой помогает не попасть в ловушку, решив, что замороженный объект полностью неизменяем. Для вложенных данных используйте рекурсию. В качестве альтернативы изменениям в следующих уроках рассматриваются шаблоны неизменяемого обновления, которые создают копии вместо заморозки.
const config = Object.freeze({ db: { host: 'local' } });
config.db.host = 'changed';
console.log('shallow freeze leaked:', config.db.host);Быстрая проверка
После вызова Object.freeze({ a: { b: 1 } }) можно ли изменить вложенное b?
Итоги: поверхностная и глубокая заморозка
Вы узнали об ограничении заморозки по глубине:
Object.freezeдействует поверхностно; вложенные объекты и массивы остаются изменяемыми.- deepFreeze рекурсивно блокирует каждый уровень.
- Защищайтесь от циклов, пропуская уже замороженные объекты.
- Глубокая заморозка требует ресурсов, поэтому замораживайте только то, что нуждается в защите.
Часто задаваемые вопросы
Урок «Поверхностная и глубокая заморозка» бесплатный?
Да — полный текст урока «Поверхностная и глубокая заморозка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Поверхностная и глубокая заморозка»?
Разберитесь, насколько глубоко распространяется заморозка. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать JavaScript Academy?
Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Поверхностная и глубокая заморозка»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке JavaScript Academy?
Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Object.freeze и seal
- Поверхностная и глубокая заморозка
- Шаблоны неизменяемого обновления
- structuredClone для глубокого копирования