Object.freeze
或的反义词是什么Object.seal
?是否有一个名称如detach的函数?
Answers:
Object.freeze(obj); thirdPartyRoutine(obj); Object.unfreeze(obj); /*continue using obj*/
我认为您可以使用一些技巧来做到:
代码在这里:
var obj = {a : 5};
console.log(obj); // {a: 5}
Object.freeze(obj);
obj.b = 10; // trying to add something to obj var
console.log(obj); // output: {a: 5} -> means its frozen
// Now use this trick
var tempObj = {};
for(var i in obj){
tempObj[i] = obj[i];
}
console.log(tempObj); // {a: 5}
// Resetting obj var
obj = tempObj;
console.log(obj);// {a: 5}
obj.b = 10; // trying to add something to obj var
console.log(obj); // output: {a: 5, b: 10} -> means it's not frozen anymore
注意:请记住一件事,不要这样做tempObj = obj
,因为tempObj
它也冻结在其中,所以它将无法工作。
在这里提琴:http : //jsfiddle.net/mpSYu/
obj != tempObj
它们的签名不再相同。
obj
,但只覆盖了本地范围。ps我个人喜欢那些物体不能被冻结。
Object.unfreeze=function(o){
var oo=undefined;
if( o instanceof Array){
oo=[];var clone=function(v){oo.push(v)};
o.forEach(clone);
}else if(o instanceof String){
oo=new String(o).toString();
}else if(typeof o =='object'){
oo={};
for (var property in o){oo[property] = o[property];}
}
return oo;
}
var obj={a:1,b:2}
// {a:1,b:2}
obj.c=3;
//{a:1,b:2,c:3}
Object.freeze(obj)
//{a:1,b:2,c:3}
obj.d=5;
//Error: Read only object
obj=Object.unfreeze(obj)
//{a:1,b:2,c:3}
obj.d=5;
//{a:1,b:2,c:3,d:5}
var tab=[1,2,3]
//[1,2,3]
tab.push(4)
//[1,2,3,4]
Object.freeze(tab);
//[1,2,3,4]
tab.push(5)
// Error : Ready only object
tab=Object.unfreeze(tab);
//[1,2,3,4]
tab.push(9)
//[1,2,3,4,9]
Object.assign
更好的选择。但是,复制/克隆也不是我想要的,
您无法解冻冻结的对象。
但是,可以通过将Object.freeze方法重写为no-op来使讨厌的库将来不再冻结任何内容:
Object.freeze = function(obj) { return obj; }; // just return the original object
在大多数情况下,这就足够了。只需在加载库之前运行上面的代码,它就不再冻结任何内容。; )
编辑:某些库(例如immer@7.0.7
)有问题,除非在之后Object.isFrozen(obj)
返回true
Object.freeze(obj)
调用。
因此,以下是阻止对象冻结的更安全方法:(原始检查是因为WeakSet
如果传入原始会出错)
const fakeFrozenObjects = new WeakSet();
function isPrimitive(val) {
return val == null || (typeof val != "object" && typeof val != "function");
}
Object.freeze = obj=>{
if (!isPrimitive(obj)) fakeFrozenObjects.add(obj);
return obj;
};
Object.isFrozen = obj=>{
if (isPrimitive(obj)) return true;
return fakeFrozenObjects.has(obj);
};
Object.freeze
发挥作用是有原因的。
您不能解冻(解冻)对象,但是如果该对象仅仅是基元的集合(没有函数或类),则可以得到对象的解冻克隆,如下所示:
const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
在FF 52中测试:
只要冻结对象的(符号)“父”对象(由代码的其他部分中的其他符号引用旁边,/或与该对象的其他符号引用进行符号引用)未冻结(例如窗口),则可以尽管如此,还是由delete-operator删除它,例如:
删除window.tinymce;
即使window.tinymce在被Object.freeze(window.tinymce)冻结之前;(否则,“父项”本身将变成某种“冻结”状态,因为它包含不可销毁的对象引用,这会使不可冻结的父项的符号不可删除...)
只要在删除/删除之前已经对原始对象进行了复制/克隆/重构/自己的版本/,就摆脱了/没有原始限制(冻结,可扩展性,可配置性,可写性等),可以将对该副本/克隆/重构/自己版本/的引用/分配给原始符号位置,就像这样:
window.tinymce = the_copy_clone_reconstruction_own_version_object;
确保解决方法代码完成后,全局范围内的“ copy_clone_reconstruction_own_version_object”不被删除![实际上,仅当对象的最后引用从任何作用域中删除时,才应该删除对象本身/释放其内存,-稍后,由于垃圾回收,但是我不确定其优先级高于“函数完成-删除所有本地变量”]
未经测试:其他符号引用也可能指向原始的冻结/受限对象,例如设置为
myobj.subobj = window.tinymce;
在您开始操作之前。
这样的东西(myobj.subobj)可能会(尝试一下!)进一步指向冻结的原始(?)。
下一个概念:未经测试!
如何使用“代理”功能包装冻结/密封或受其他限制(可扩展性,...)对象的值获取/设置和其他行为(功能,...)?在GLOBAL范围内创建,例如p = new Proxy(target,handler); 或window.p =新代理(目标,处理程序);
//其中target是要包装以进行拦截/挂钩/监视的对象,例如“ window.tinymce”
代理主题的mdn-doc表示,保留了对包装对象的限制(冻结,...),但是这可能是指核心/原始对象本身(由代理包装),并且可能最终不参考代理人的模仿...
范围规则可能如上所述适用...
我也是那个问题。要修复它,我使用了JavaScript JSON API来解冻我的对象:const unfreezeObject = JSON.parse(JSON.stringify(freezeObject))
。之后,我做了所有需要的突变。
{ ...item }
否则可能只需要浅表副本即可。
您可以使用传播运算符解冻数组。
//let suppose arr is a frozen array i.e. immutable
var arr = [1, 2, 3];
//if arr is frozen arr you cannot mutate any array referring to it
var temp = arr;
temp.push(4); //throws an error "Cannot modify frozen array elements"
//here mutableArr gets the elements of arr but not reference to it
//hence you can mutate the mutableArr
var mutableArr = [...arr];
mutableArr.push(4); //executes successfully