我在MDN上学习了更多有关JavaScript Object
构造函数的方法,我注意到Object.freeze's description的最后一句是:
请注意,仍然可以修改作为对象的值,除非它们也被冻结。
这样的行为似乎应该选择加入。必须递归地手动冻结冻结对象的对象有什么好处?
答案 0 :(得分:13)
我认为如果递归是默认策略,则某些复杂的对象无法按预期运行。 考虑以下情况:
<div id="root">
<div id="stem">
<div id="leaf>
</div>
</div>
</div>
由于某种原因我想冻结stem
,所以我写了这些代码:
Object.freeze(document.getElementById('stem'));
如果它以递归方式冻结,leaf
也会被冻结,似乎没问题:如果我要冻结stem
,我也想冻结它的孩子。
但请稍等,请注意stem
还有另一个属性 - 它也有parentElement
。那会发生什么?当我冻结stem
时,我也会冻结stem.parentElement
和stem.parentElement.parentElement
......这绝不是我想要的。
答案 1 :(得分:6)
答案就在于这一点
Note that values that are objects can still be modified, unless they are also frozen.
<强>更新强>
没有关于freeze()方法的设计决定的任何官方信息
我认为,基本上对于性能原因他们已经做出了这个决定,如果我们想让内部对象也被冻结,我们将不得不递归地应用方法 。所以这是一个很大的开销,所以做出了设计决定以避免这种情况。
如果不是性能,该方法就会表现出来 不同。强>
答案 2 :(得分:1)
在考虑更多之后,可能是为了防止冻结在其他地方也被引用的引用对象(从而禁用使用同一对象的另一部分代码)。我对此的回应是:
我并不是建议这样做。如果完全捕获对象的状态,Object.freeze()
会更有意义。引用(对象)本身可以是不可变的,但引用的对象不会被冻结。
如果我这样做......
var friend = {
name: 'Alec',
likes: {
programming: true,
reading: true,
cooking: false
}
};
// Pass as frozen object
doStuff(Object.freeze(friend));
document.addEventListener('click', function () {
friend.likes.clicking = true;
});
...我不希望name
被更改和我不希望朋友的likes
被{{更改} 1}}。但我仍然希望能够从事件监听器更改doStuff()
(就像我可以更改likes
),例如,没有name
对doStuff()
的对象引用也改变了。
编辑:在阅读了Shaik的回答之后,我理解他们为什么这样做。现在,为了获得本例中我需要的功能,我会这样做:
friend
这有什么固有的问题吗?
答案 3 :(得分:0)
这一切都取决于具体情况。您可能希望冻结对象以防止添加或删除新属性集,但是您可能希望更改现有属性。如果你不这样做,就冻结吧! IIRC,你只能冻结父对象。子对象也需要递归冻结。