0Pricing
JavaScript Academy · Урок

Поверхностная и глубокая заморозка

Разберитесь, насколько глубоко распространяется заморозка.

«Поверхностная и глубокая заморозка» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Object.freeze и seal
  2. Поверхностная и глубокая заморозка
  3. Шаблоны неизменяемого обновления
  4. structuredClone для глубокого копирования
← Назад к JavaScript Academy