Spec-Zone.ru › JavaScript

Object.freeze()

Базовая поддержка Широко доступно

Эта функция хорошо зарекомендовала себя и работает во многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

Статический метод Object.freeze() замораживает объект. Замораживание объекта предотвращает расширение и делает существующие свойства незаписываемыми и неконфигурируемыми. Замороженный объект больше нельзя изменить: нельзя добавлять новые свойства, удалять существующие свойства, изменять их перечисляемость, конфигурируемость, записываемость или значение, а также нельзя переназначать прототип объекта. freeze() возвращает тот же объект, который был передан.

Замораживание объекта — это самый высокий уровень целостности, который предоставляет JavaScript.

Попробуйте это

const obj = {
  prop: 42,
};

Object.freeze(obj);

obj.prop = 33;
// Throws an error in strict mode

console.log(obj.prop);
// Expected output: 42

Синтаксис

Object.freeze(obj)

Параметры

obj
Объект для замораживания.

Возвращаемое значение

Объект, который был передан функции.

Описание

Замораживание объекта эквивалентно предотвращению расширений, а затем изменению configurable всех существующих дескрипторов свойств на false, а для свойств данных — также writable на false. Ничего нельзя добавить или удалить из набора свойств замороженного объекта. Любая попытка сделать это завершится неудачей, либо молча, либо путем возбуждения исключения TypeError (чаще всего, но не исключительно, в строгом режиме).

Для свойств данных замороженного объекта их значения не могут быть изменены, так как атрибуты writable и configurable установлены в false. Свойства доступа (геттеры и сеттеры) работают так же — значение свойства, возвращаемое геттером, может все еще меняться, и сеттер все еще может быть вызван без генерации ошибок при установке свойства. Обратите внимание, что значения, которые являются объектами, могут быть изменены, если только они также не заморожены. Как объект, массив может быть заморожен; после этого его элементы не могут быть изменены, и никакие элементы не могут быть добавлены или удалены из массива.

Приватные элементы не являются свойствами и не имеют концепции дескрипторов свойств. Замораживание объекта с приватными элементами не препятствует изменению значений этих приватных элементов. (Замораживание объектов обычно предназначено в качестве меры безопасности против внешнего кода, но внешний код все равно не может получить доступ к приватным элементам.) Приватные элементы не могут быть добавлены или удалены из объекта, независимо от того, заморожен объект или нет.

freeze() возвращает тот же объект, который был передан функции. Он не создает замороженную копию.

Использование TypedArray или DataView с элементами вызовет TypeError, поскольку они являются представлениями памяти и определенно вызовут другие возможные проблемы:

Object.freeze(new Uint8Array(0)); // No elements
// Uint8Array []

Object.freeze(new Uint8Array(1)); // Has elements
// TypeError: Cannot freeze array buffer views with elements

Object.freeze(new DataView(new ArrayBuffer(32))); // No elements
// DataView {}

Object.freeze(new Float64Array(new ArrayBuffer(64), 32, 0)); // No elements
// Float64Array []

Object.freeze(new Float64Array(new ArrayBuffer(64), 32, 2)); // Has elements
// TypeError: Cannot freeze array buffer views with elements

Обратите внимание, что поскольку стандартные три свойства (buf.byteLength, buf.byteOffset и buf.buffer) доступны только для чтения (как и свойства ArrayBuffer или SharedArrayBuffer), нет причин пытаться заморозить эти свойства.

В отличие от Object.seal(), существующие свойства в объектах, замороженных с помощью Object.freeze(), становятся неизменяемыми, а свойствам данных нельзя повторно присваивать значения.

Примеры

Замораживание объектов

const obj = {
  prop() {},
  foo: "bar",
};

// Before freezing: new properties may be added,
// and existing properties may be changed or removed
obj.foo = "baz";
obj.lumpy = "woof";
delete obj.prop;

// Freeze.
const o = Object.freeze(obj);

// The return value is just the same object we passed in.
o === obj; // true

// The object has become frozen.
Object.isFrozen(obj); // === true

// Now any changes will fail
obj.foo = "quux"; // silently does nothing
// silently doesn't add the property
obj.quaxxor = "the friendly duck";

// In strict mode such attempts will throw TypeErrors
function fail() {
  "use strict";
  obj.foo = "sparky"; // throws a TypeError
  delete obj.foo; // throws a TypeError
  delete obj.quaxxor; // returns true since attribute 'quaxxor' was never added
  obj.sparky = "arf"; // throws a TypeError
}

fail();

// Attempted changes through Object.defineProperty;
// both statements below throw a TypeError.
Object.defineProperty(obj, "ohai", { value: 17 });
Object.defineProperty(obj, "foo", { value: "eit" });

// It's also impossible to change the prototype
// both statements below will throw a TypeError.
Object.setPrototypeOf(obj, { x: 20 });
obj.__proto__ = { x: 20 };

Замораживание массивов

const a = [0];
Object.freeze(a); // The array cannot be modified now.

a[0] = 1; // fails silently

// In strict mode such attempt will throw a TypeError
function fail() {
  "use strict";
  a[0] = 1;
}

fail();

// Attempted to push
a.push(2); // throws a TypeError

Замораживаемый объект является неизменяемым. Однако он не обязательно является константой. Следующий пример показывает, что замороженный объект не является константой (заморозка является поверхностной).

const obj1 = {
  internal: {},
};

Object.freeze(obj1);
obj1.internal.a = "value";

obj1.internal.a; // 'value'

Чтобы быть константным объектом, весь граф ссылок (прямые и косвенные ссылки на другие объекты) должен ссылаться только на неизменяемые замороженные объекты. Замораживаемый объект считается неизменяемым, поскольку все состояние объекта (значения и ссылки на другие объекты) в пределах всего объекта фиксировано. Обратите внимание, что строки, числа и логические значения всегда неизменяемы, а функции и массивы являются объектами.

Глубокое замораживание

Результат вызова Object.freeze(object) применяется только к непосредственным свойствам самого object и предотвратит будущие операции добавления, удаления или повторного присваивания значений свойств только для object. Если значения этих свойств сами являются объектами, то эти объекты не заморожены и могут быть целью операций добавления, удаления или повторного присваивания значений свойств.

const employee = {
  name: "Mayank",
  designation: "Developer",
  address: {
    street: "Rohini",
    city: "Delhi",
  },
};

Object.freeze(employee);

employee.name = "Dummy"; // fails silently in non-strict mode
employee.address.city = "Noida"; // attributes of child object can be modified

console.log(employee.address.city); // "Noida"

Чтобы сделать объект неизменяемым, рекурсивно заморозьте каждое непримитивное свойство (глубокое замораживание). Используйте этот шаблон в каждом конкретном случае, основываясь на вашем дизайне, когда вы знаете, что объект не содержит циклов в графе ссылок, иначе будет вызван бесконечный цикл. Например, функции, созданные с помощью синтаксиса function, имеют свойство prototype со свойством constructor, которое указывает на саму функцию, поэтому они по умолчанию имеют циклы. Другие функции, такие как стрелочные функции, все еще могут быть заморожены.

Улучшением для deepFreeze() было бы сохранение объектов, которые он уже посетил, чтобы вы могли подавить рекурсивный вызов deepFreeze(), когда объект находится в процессе превращения в неизменяемый. Например, см. использование WeakSet для обнаружения циклических ссылок. Вы все равно рискуете заморозить объект, который не должен быть заморожен, например, window.

function deepFreeze(object) {
  // Retrieve the property names defined on object
  const propNames = Reflect.ownKeys(object);

  // Freeze properties before freezing self
  for (const name of propNames) {
    const value = object[name];

    if ((value && typeof value === "object") || typeof value === "function") {
      deepFreeze(value);
    }
  }

  return Object.freeze(object);
}

const obj2 = {
  internal: {
    a: null,
  },
};

deepFreeze(obj2);

obj2.internal.a = "anotherValue"; // fails silently in non-strict mode
obj2.internal.a; // null

Спецификации

Спецификация
Спецификация языка ECMAScript® 2027
# sec-object.freeze

Совместимость с браузерами

Настольные Мобильные Серверные
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
freeze
6
12
4
12
5.1
18
4
12
5
1.0
4.4
5
1.0.0
1.0
0.10.0

Смотрите также

  • Object.isFrozen()
  • Object.preventExtensions()
  • Object.isExtensible()
  • Object.seal()
  • Object.isSealed()

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API