Object.freeze
或Object.seal
的反义词是什么?是否有名为“detach”之类的函数?
Object.freeze
或Object.seal
的反义词是什么?是否有名为“detach”之类的函数?
一旦对象被冻结,就没有办法解冻它。这是一种终极的锁定形式,冻结后的对象无法被修改。这是确保您的对象永久保持不变的最佳方式。
冻结对象是最终的锁定形式。一旦对象被冻结,就不能解冻,也不能以任何方式篡改。这是确保您的对象永远保持原样的最佳方式。
Object.freeze(obj); thirdPartyRoutine(obj); Object.unfreeze(obj); /*继续使用obj*/
。如果能实现这一点,那将是非常棒的。 - trusktrfreeze
(锁定)函数返回一个 key
以便后续 unfreeze
(解锁)操作是有意义的。 - Ghost4Man我认为你可以使用一些技巧:
代码如下:
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
也被冻结在那里。obj != tempObj
- 他们的签名不再相同。 - CodingIntrigue无法解冻已经被冻结的对象。
但是,您可以通过覆盖 Object.freeze 方法使讨厌的库无法在将来冻结任何内容:
Object.freeze = function(obj) { return obj; }; // just return the original object
在大多数情况下这已经足够了。只需在库加载之前运行上面的代码,它就无法再冻结任何东西了。;)
编辑:一些库(例如immer@7.0.7
)存在问题,除非在调用Object.freeze(obj)
后Object.isFrozen(obj)
返回true
。
以下是一个更安全的防止对象冻结的方法:(原始检查是因为如果传递原始值,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
的工作方式有其原因。 - CodingIntrigue 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
是更好的选择。然而,复制/克隆也不是我要寻找的。 - ghiscoding您无法解冻(thaw)一个对象,但是如果对象只是由原始数据类型组成的集合(没有函数或类),您可以通过以下方式获得一个解冻的克隆对象:
const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
根据回答和评论,似乎人们在需要改变冻结对象时会找到这篇文章。虽然说“这是不可能的”是准确的,但并不是很有帮助。
考虑到这一点,这里是我基于@Abdennour TOUMI 2014年的答案而提出的现代变体。
function unfreeze(obj) {
if (Object.isFrozen(obj)) {
return Object.assign({}, obj);
}
return obj;
}
let myObj = { one: "1", two: "2", three: "3" };
Object.freeze(myObj);
// error
// myObj.one = "4";
// succeeds
myObj = unfreeze(myObj);
myObj.one = "4";
function IMap(key, value) {
let frozen = false;
this.lock = function lock() {
frozen = true;
return this;
};
this.unlock = function unlock(password) {
if (!password) {
throw Error("Empty IMap key.");
}
if (password === key) {
frozen = false;
} else {
throw Error(`Wrong IMap unlock key.`);
}
return this;
};
this.set = function set(prop, val) {
if (!frozen) {
value[prop] = val;
} else {
throw TypeError("IMap is locked.");
}
return this;
};
this.get = function get(prop) {
return value[prop];
};
}
export function iMap(password, source) {
return new IMap(password, source);
}
用法:
const item = iMap('your-password',{ something: 'value' });
item.lock();
item.set('something',5); // throws an error
item.unlock('your-password').set('something',5).lock(); // ok
我也遇到了这个问题。为了解决它,我使用了JavaScript JSON API来解冻我的对象:const unfreezeObject = JSON.parse(JSON.stringify(freezeObject))
。之后,我进行了所有必要的变异。
{...item}
可能就足够了。 - TamusJRoyce我认为,如果您想保留原始对象,但仍然具有未冻结的行为,则唯一剩下的逻辑是创建一个具有原始对象相同行为的子类,然后在子类内部,通过创建可变访问器来覆盖现有对象的行为,从而覆盖您想要更改的访问器。
这样,如果您仍然希望出于某种奇怪的原因保留原始变量/对象,或者保持系统的其余部分一致,那么您可以将其保持不变,同时使用直接继承自原始对象的子类版本,以获得其现有行为的好处,而无需重新制作原始父对象。我看不出试图做不可能或不合逻辑的事情似乎是如此令人向往的事情。
除非您创建子类,否则您只是在做不可能的事情。
let
)中创建一个对象,并在需要重置时将原始对象重新分配给变量。let obj = { objProp: "example" };
if (condition) {
Object.freeze(obj);
}
else {
obj = { objProp: "example" };
}