Javascript中冻结和密封的区别

maj*_*aja 146 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"
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*ngo 179

Object.seal

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

Object.freeze

  • 究竟是什么Object.seal,再加上:
  • 它可以防止修改任何现有属性

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


性能:

密封或冻结对象可能会影响其枚举速度,具体取决于浏览器:

  • Firefox:枚举性能不受影响
  • IE:枚举性能影响可以忽略不计
  • Chrome:密封或冻结对象的枚举性能更快
  • Safari:密封或冷冻物品的速度减慢92%(截至2014年)

测试:密封物体,冷冻物体.

  • FWIW,冷冻和密封物体现在比Chrome Canary v43.0.2317.0中未冻结和未密封的物体更快. (8认同)
  • 在未来,我认为在开发库/框架时,它们将被大量使用(如果正确优化).它们允许您阻止用户(甚至无意中)破坏您的代码(并且,如答案中所述,优化应该会带来极大的速度提升).但这是纯粹的猜测:) (3认同)
  • 你能谈谈为什么我们会使用这些方法吗?只是因为我们可以? (2认同)
  • 这个答案有许多事实错误.例如,`seal`也使现有属性不可配置,请参阅http://jsfiddle.net/btipling/6m743whn/ Number 2,您仍然可以编辑,即更改密封对象上现有属性的值. (2认同)
  • @AlanDong来晚了一点,但这就是为什么要锁定对象的原因。JavaScript的功能之一是您可以随时添加属性。您也可以通过错误键入_accidentally_进行此操作。我的许多学生都试图添加一个名为“ onClick”或“ onlick”的事件处理程序,并想知道为什么它不起作用。如果JavaScript引发错误,那么出错就少了一件。其次,这允许您对防止更改的对象实施常量属性。这对于对象方法特别有用。 (2认同)

pie*_*hka 96

我写了一个比较这三种方法的测试项目:

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

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

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

结果:

在此输入图像描述

  • 在这种情况下,也许用“ EXTEND”代替“ CREATE”会更具表现力。 (3认同)
  • 太好了 UPDATE是否考虑(通过defineProperty)修改描述符属性,例如可配置,可枚举,可写? (2认同)
  • @寂寞然后它不会拼写CRUD。您必须适应像RUDE;) (2认同)

tun*_*ngd 81

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

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

  • `Object.seal()` 似乎也冻结了原型属性:\ (2认同)

Shw*_*har 18

我创建了一个简单的表格来比较以下函数并解释这些函数之间的差异。

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

表格解释了上述三种方法之间的区别


shm*_*uli 8

Object.freeze()创建一个冻结对象,这意味着它接受一个现有对象并基本上调用Object.seal()它,但它也将所有"数据访问器"属性标记为writable:false,以便它们的值不能更改. - 凯尔辛普森,你不知道JS - 这和对象的原型


Jay*_*cee 5

我正在查看 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());
}
Run Code Online (Sandbox Code Playgroud)