冷冻和密封之间的区别

时间:2014-01-28 09:50:25

标签: javascript ecmascript-5

我刚刚听说过JavaScript方法freezeseal,它们可用于使任何对象不可变。

以下是如何使用它的简短示例:

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

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

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

freezeseal之间有什么区别?他们能提高绩效吗?

8 个答案:

答案 0 :(得分:165)

Object.seal

  • 防止从密封物体添加和/或移除物品;使用delete将返回false
  • 它使每个现有属性non-configurable:它们不能从“数据描述符”转换为“访问者描述符”(反之亦然),并且根本不能修改访问者描述符的属性(而数据描述符可以如果writable为真,则更改其value属性及其writeable属性。
  • 尝试修改密封对象本身的值时可以抛出TypeError(最常见的是严格模式

Object.freeze

  • 正是Object.seal的作用,加上:
  • 它会阻止修改任何现有属性

两者都不会影响'深'/孙子对象。例如,如果冻结obj,则无法重新分配obj.el,但可以修改obj.el的值,例如obj.el.id可以更改。


性能:

根据浏览器的不同,封闭或冻结对象可能会影响其枚举速度:

  • Firefox:枚举性能不受影响
  • IE:枚举性能影响微不足道
  • Chrome:密封或冻结对象的枚举性能更快
  • Safari:密封或冻结的对象计算速度慢92%(截至2014年)

测试:Sealed objectsFrozen objects

答案 1 :(得分:80)

您始终可以在MDN中查找这些内容。简而言之:

  • Freeze:使对象不可变,这意味着不允许更改已定义的属性,除非它们是对象。
  • Seal:阻止添加属性,但仍可以更改已定义的属性。

答案 2 :(得分:74)

我写了一个test project来比较这三种方法:

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

我的单元测试涵盖了CRUD案例:

  • [C]添加新属性
  • [R]读取已存在的财产
  • [U]修改已存在的属性
  • [D]删除已存在的财产

结果:

enter image description here

答案 3 :(得分:7)

Object.freeze()创建一个冻结对象,这意味着它需要一个 现有的对象并且基本上在其上调用Object.seal(),但它也是 将所有“数据访问者”属性标记为writable:false,以便将其标记为{{1}} 值无法更改。 - Kyle Simpson,你不知道JS - 这个&对象原型

答案 4 :(得分:3)

我正在研究ECMAScript 5中Freeze和Seal之间的差异,并创建了一个脚本来澄清差异。 Frozen创建了一个包含数据和结构的不可变对象。 Seal阻止对命名接口的更改 - 不添加,删除 - 但您可以改变对象并重新定义其接口的含义。

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());
}

答案 5 :(得分:3)

我创建了一个简单的表格来比较以下功能并解释这些功能之间的区别。

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

table that explains the difference between the above three methods

答案 6 :(得分:2)

我知道我可能会迟到但

  • 相似性:它们都用于创建不可扩展 对象即可。
  • 区别:冻结 可配置,可枚举和可写 对象的属性设置为directives: [AddClass]。在密封的地方 可写 属性设置为false,其余属性为false。

答案 7 :(得分:0)

现在可以强制冻结单个对象属性,而不是冻结整个对象。您可以使用rep_len(monthName, length(entry$test)) Object.defineProperty作为参数来实现此目的。

writable: false

在此示例中,var obj = { "first": 1, "second": 2, "third": 3 }; Object.defineProperty(obj, "first", { writable: false, value: 99 }); 现在将其值锁定为99。