Javascript中冻结和密封的区别

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

这里有一个简单的例子来说明如何使用它:

 var o1 = {}, o2 = {}; Object.freeze(o2); o1["a"] = "worked"; o2["a"] = "worked"; alert(o1["a"]); //prints "worked" alert(o2["a"]); //prints "undefined" 

这些方法有什么区别,它们可以提高性能吗?

Object.seal

  • 它防止添加和/或删除密封对象的属性
  • 尝试修改时可能会抛出TypeError (通常在严格模式下
  • 使用delete将返回false
  • 它使每个属性都是不可configuration的,并且不能将其从数据访问器转换为属性(反之亦然)

Object.freeze

  • 究竟是什么Object.seal ,加上:
  • 它防止改变任何现有的属性

两者都不影响子对象(例如,如果obj被冻结或封闭, obj.el不能被改变,但是obj.el.id可以)

至于性能,密封或冻结对象可以降低浏览器的枚举速度。

  • Firefox:枚举性能不受影响
  • IE:枚举性能影响可以忽略不计
  • Chrome:枚举性能不受影响
  • Safari:密封和冻结的对象枚举速度慢92%

testing: 密封的物体 , 冻结的物体 。

这很奇怪,因为密封和冻结应该允许引擎做一些强大的优化(对于冻结对象比密封对象更多),但是看起来,因为它们是“新”function,所以它们还没有被优化。 请把这个作为一个假设 ,因为我不知道在两种情况下他们的速度慢的原因。

您可以随时在MDN中查看这些信息。 简而言之:

  • 冻结 :使对象不可变,意味着不允许改变定义的属性,除非它们是对象。
  • 密封 :防止添加属性,但是定义的属性仍然可以改变。

我写了一个testing项目 ,比较这三种方法:

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

我的unit testing涵盖了CRUD的情况:

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

结果:

在这里输入图像说明

Object.freeze()创build一个冻结的对象,这意味着它需要一个现有的对象,本质上调用Object.seal() ,但它也标记所有的“数据访问器”属性为writable:false ,所以他们的值不能改变。 – 凯尔辛普森,你不知道JS – 这个&对象原型

我正在研究ECMAScript 5中Freeze和Seal之间的区别,并创build了一个脚本来阐明差异。 冻结创build一个不可变的对象,包括数据和结构。 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()); } 

我知道我可能会迟到,但是

  • 相似性:它们都用于创build不可扩展的对象
  • 差异:在冻结可configuration,对象的可枚举和可写属性设置为false 。 其中密封的可写属性设置为true ,其余属性为false。

现在可以强制冻结单个对象属性而不冻结整个对象。 你可以用Object.defineProperty来实现这个Object.definePropertywritable: false作为参数。

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

在这个例子中, obj.first现在将其值locking为99。