Разница между замораживанием и печатью в Javascript

Я только что услышал о методах JavaScript freeze и seal, которые могут быть использованы для того, чтобы сделать любой объект неизменным.

Вот краткий пример того, как его использовать:

var o1 = {}, o2 = {};
Object.freeze(o2);

o1["a"] = "worked";
o2["a"] = "worked";

alert(o1["a"]);   //prints "worked"
alert(o2["a"]);   //prints "undefined"

В чем разница между этими методами и может ли они повысить производительность?

Ответ 1

Object.seal

  • Это предотвращает добавление и/или удаление свойств из запечатанного объекта; использование delete вернет false
  • Это делает каждое существующее свойство неконфигурируемым: они не могут быть преобразованы из "дескрипторов данных" в "дескрипторы доступа" (и наоборот), и никакой атрибут дескрипторов доступа не может быть изменен вообще (тогда как дескрипторы данных могут изменить свой атрибут writable, и их value атрибута, если writeable true).
  • Может TypeError при попытке изменить значение самого запечатанного объекта (чаще всего в строгом режиме)

Object.freeze

  • Именно то, что делает Object.seal, плюс:
  • Это предотвращает изменение любых существующих свойств

Ни один из них не влияет на "глубокие"/внуковые объекты. Например, если obj заморожен, obj.el может быть переназначен, но значение obj.el может быть изменено, например, obj.el.id может быть изменено.


Спектакль:

Запечатывание или замораживание объекта может повлиять на скорость его перечисления, в зависимости от браузера:

  • Firefox: на производительность перечисления это не влияет
  • IE: влияние на производительность перечисления незначительно
  • Хром: производительность перечисления быстрее с запечатанными или замороженными объектами
  • Safari: закрытые или замороженные объекты подсчитывают на 92% медленнее (по состоянию на 2014 год)

Тесты: Запечатанные объекты, Замороженные объекты.

Ответ 2

Вы всегда можете посмотреть их в MDN. Короче говоря:

  • Freeze: делает объект неизменным, что означает, что никакое изменение в разрешенное свойство не допускается, если только они не являются объектами.
  • Seal: предотвратить добавление свойств, однако определенные свойства по-прежнему могут быть изменены.

Ответ 3

Я написал проект , который сравнивает эти 3 метода:

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

Мои модульные тесты охватывают случаи CRUD:

  • [C] добавить новое свойство
  • [R] читать существующее свойство
  • [U] изменить существующее свойство
  • [D] удалить существующее свойство

Результат:

enter image description here

Ответ 4

Object.freeze() создает замороженный объект, что означает, что он принимает существующий объект и по существу вызывает на нем Object.seal(), но он также маркирует все свойства "data accessor" как writable:false, так что их значения не могут быть изменены. - Кайл Симпсон, вы не знаете JS - это и прототипы объектов

Ответ 5

Я рассматривал различия между Freeze и Seal в ECMAScript 5 и создал script, чтобы прояснить различия. Frozen создает неизменяемый объект, включая данные и структуру. Печать предотвращает изменения названных интерфейсов - не добавляет, не удаляет - но вы можете мутировать объект и переопределять смысл его интерфейса.

function run()
{
    var myObject = function() 
    { 
        this.test = "testing"; 
    }

    //***************************SETUP****************************

    var frozenObj = new myObject();
    var sealedObj = new myObject();

    var allFrozen = Object.freeze(frozenObj);
    var allSealed = Object.seal(sealedObj);
    alert("frozenObj of myObject type now frozen - Property test= " + frozenObj.test);
    alert("sealedObj of myObject type now frozen - Property test= " + sealedObj.test);

    //***************************FROZEN****************************

    frozenObj.addedProperty = "added Property"; //ignores add
    alert("Frozen addedProperty= " + frozenObj.addedProperty);
    delete frozenObj.test; //ignores delete
    alert("Frozen so deleted property still exists= " + frozenObj.test);
    frozenObj.test = "Howdy"; //ignores update
    alert("Frozen ignores update to value= " + frozenObj.test);
    frozenObj.test = function() { return "function"; } //ignores
    alert("Frozen so ignores redefinition of value= " + frozenObj.test);

    alert("Is frozen " + Object.isFrozen(frozenObj));
    alert("Is sealed " + Object.isSealed(frozenObj));
    alert("Is extensible " + Object.isExtensible(frozenObj));

    alert("Cannot unfreeze");
    alert("result of freeze same as the original object: " + (frozenObj === allFrozen).toString());

    alert("Date.now = " + Date.now());

    //***************************SEALED****************************

    sealedObj.addedProperty = "added Property"; //ignores add
    alert("Sealed addedProperty= " + sealedObj.addedProperty);
    sealedObj.test = "Howdy"; //allows update
    alert("Sealed allows update to value unlike frozen= " + sealedObj.test);
    sealedObj.test = function() { return "function"; } //allows
    alert("Sealed allows redefinition of value unlike frozen= " + sealedObj.test);
    delete sealedObj.test; //ignores delete
    alert("Sealed so deleted property still exists= " + sealedObj.test);
    alert("Is frozen " + Object.isFrozen(sealedObj));
    alert("Is sealed " + Object.isSealed(sealedObj));
    alert("Is extensible " + Object.isExtensible(sealedObj));

    alert("Cannot unseal");
    alert("result of seal same as the original object: " + (sealedObj === allSealed).toString());

    alert("Date.now = " + Date.now());
}

Ответ 6

Я знаю, что может быть немного поздно, но

  • Сходство: оба из них используются для создания не расширяемых объекты.
  • Разница: во Freeze настраивается, перечислима и доступна для записи атрибуты объекта установлены на false. где, как и в Sealed записываемый атрибут имеет значение true, а остальные атрибуты - false.

Ответ 7

Теперь вы можете принудительно заморозить одно свойство объекта, а не замораживать весь объект. Вы можете достичь этого с помощью Object.defineProperty с writable: false в качестве параметра.

var obj = {
    "first": 1,
    "second": 2,
    "third": 3
};
Object.defineProperty(obj, "first", {
    writable: false,
    value: 99
});

В этом примере obj.first теперь имеет значение, заблокированное до 99.