75

Object.freezeor的反义词是Object.seal什么?是否有一个名称为 detach 的函数?

4

10 回答 10

112

没有办法做到这一点,一旦对象被冻结,就无法解冻它。

资源

冻结对象是锁定的最终形式。一旦一个物体被冻结,它就不能被解冻——也不能以任何方式被篡改。这是确保您的对象无限期地保持原样的最佳方法

于 2013-10-10T10:34:59.423 回答
19

我认为你可以做到,使用一些技巧:

  • 首先创建原始对象的重复临时变量
  • 然后将原始变量设置为未定义
  • 从临时重置它的值。

代码在这里:

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/

于 2014-01-16T11:17:31.247 回答
14

有线解决方案:)

 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]
于 2014-11-05T08:15:06.007 回答
12

您无法解冻冻结的对象。

但是,您可以通过将 Object.freeze 方法重写为无操作,使讨厌的库将来无法冻结任何内容:

Object.freeze = function(obj) { return obj; }; // just return the original object

在大多数情况下,这就足够了。只需在加载库之前运行上面的代码,它就不能再冻结任何东西。; )


编辑:某些库,例如,除非在调用之后返回immer@7.0.7,否则会出现问题。Object.isFrozen(obj)trueObject.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);
};
于 2016-08-31T15:21:06.913 回答
4

您不能解冻(解冻)对象,但如果对象只是基元的集合(没有函数或类),您可以像这样获得对象的解冻克隆:

const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
于 2018-03-28T09:43:55.563 回答
1

根据答案和评论,人们似乎在需要对冻结对象进行变异时会找到此帖子。说“那是不可能的”虽然准确,但并不是那么有帮助。

考虑到这一点,这是我根据 2014 年的@Abdennour TOUMI 回答提出的现代变体

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";

于 2021-07-11T18:55:31.833 回答
0

在 FF 52 中测试:

至于冻结对象的(符号)“父”对象(它被符号引用,除了/除了代码的其他部分对同一对象的其他符号引用之外)不是冻结的(如窗口),一个可以尽管如此,还是由删除操作员删除它,例如:

删除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)可能会(试一试!)进一步指向冻结的原件(?)。

下一个概念:未经测试!

如何使用“代理”功能来包装冻结/密封或其他受限(可扩展性,...)对象的 value-get/-set 和其他行为(函数,...)?在全球范围内创建,例如 p = new Proxy(target, handler); 或 window.p = new Proxy(target, handler);
// 其中 target 是要为拦截/挂钩/监控包装的对象,例如“window.tinymce”

代理主题的 mdn-doc 说,被包装对象的限制(冻结,...)被保留,但这可能指核心/原始对象本身(由代理包装)并最终可能不要指代代理制作的模仿...

如上所述,范围规则可能适用...

于 2017-08-13T17:03:48.547 回答
0

我也是这个问题。为了修复它,我使用 JavaScript JSON API 来解冻我的对象:const unfreezeObject = JSON.parse(JSON.stringify(freezeObject)). 之后,我做了所有我需要的突变。

于 2018-06-08T13:10:56.570 回答
0

晚了一点,但您也可以在可变变量 ( ) 中创建一个对象let,并在需要重置它时将原始对象重新分配给该变量。

例如:

let obj = { objProp: "example" };

if (condition) {
    Object.freeze(obj);
}
else {
    obj = { objProp: "example" };
}
于 2020-11-04T23:13:17.407 回答
-2

您可以使用扩展运算符解冻数组。

//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 
于 2018-05-31T07:54:19.920 回答