JavaScript中Object.freeze或Object.seal的对面

JavaScript中Object.freeze或Object.seal的对面,javascript,locking,freeze,Javascript,Locking,Freeze,什么是Object.freeze或Object.seal的对立面?是否有一个名为detach的函数?没有办法做到这一点,一旦对象被冻结,就没有办法解冻它 冻结对象是锁定的最终形式。曾经是一个物体 已经冻结,不能解冻,也不能以任何方式篡改 态度。这是确保对象保持不变的最佳方法 就像你离开他们一样,无限期 我想你可以用一些技巧做到: 首先为原始对象创建一个重复的临时变量 然后将原始变量设置为未定义 将从临时设置中重置其值 此处代码: var obj = {a : 5}; console.lo

什么是
Object.freeze
Object.seal
的对立面?是否有一个名为detach的函数?

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

冻结对象是锁定的最终形式。曾经是一个物体 已经冻结,不能解冻,也不能以任何方式篡改 态度。这是确保对象保持不变的最佳方法 就像你离开他们一样,无限期


我想你可以用一些技巧做到:

  • 首先为原始对象创建一个重复的临时变量
  • 然后将原始变量设置为未定义
  • 将从临时设置中重置其值
此处代码:

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
也被冻结在那里

在这里摆弄:

有线解决方案:) 最佳做法:


无法解冻冻结的对象

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

Object.freeze = function(obj) { return obj; }; // just return the original object
在大多数情况下,这就足够了。只要在加载库之前运行上面的代码,它就不能再冻结任何内容了。;)


编辑:一些库,例如
immer@7.0.7
,除非调用
Object.isfreeze(obj)
对象冻结(obj)后返回
true
,否则会出现问题

因此,下面是阻止对象冻结的更安全的方法:(原语检查是因为传入原语时出现
WeakSet
错误)

在FF 52中测试:

只要冻结对象的(符号)“父”对象(在同一对象的代码的其他部分中,除了其他符号引用之外,它被符号引用)没有冻结(如窗口),就可以通过delete操作符删除它,如:

删除window.tinymce

即使之前Object.freeze(window.tinymce)冻结了window.tinymce; (否则,“父对象”本身将成为某种“冻结”对象,因为它包含不可销毁的对象引用,这将使未冻结父对象的符号不可删除……)

只要在删除/删除之前已经对原始对象进行了复制/克隆/重建/拥有自己的版本/且没有原始限制(冻结、可扩展性、可配置性、可写性等),可以将对该副本/克隆/重建/自有版本/的引用放置/分配到原始符号位置,如下所示:

window.tinymce=复制、克隆、重建、拥有、版本对象

确保“复制\克隆\重建\拥有\版本\对象”在全局范围内,以免在解决方案代码完成后被删除! [实际上,对象本身应该被删除/它的内存被释放/仅当对它的最后一个引用被从任何作用域中删除时,-一段时间后,由于垃圾收集,但我不确定优先级是否高于“函数完成-删除所有本地变量”]

未测试: 其他符号引用可能指向原始的、冻结的/受限的对象,更进一步说,类似于设置为

myobj.subobj=window.tinymce

在你的手术开始之前

像这样的东西(myobj.subobj)可能会(尝试一下!)进一步指向冻结的原版(?)

下一个概念: 没有测试

如何使用“代理”功能包装冻结/密封或受限(可扩展性…)对象的值get/-set和其他行为(函数…)呢? 在全局范围内创建,如 p=新代理(目标、处理程序); 或 p=新代理(目标,处理程序)
//其中,target是用于拦截/挂接/监视的包装对象,例如“window.tinymce”

代理主题的mdn文档说,被包装对象的限制(冻结,…)会一直被考虑,但这可能指的是核心/原始对象本身(由代理包装),最终可能不会指的是代理所做的模拟

作用域规则可能如上所述应用…

您无法解冻(解冻)对象,但如果对象只是一组基本体(没有函数或类),则可以获得解冻后的对象克隆,如下所示:

const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));

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

//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 

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

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

例如:

let obj={objProp:“example”};
如果(条件){
冻结(obj);
}
否则{
obj={objProp:“示例”};
}

我明白你的意思。复制这些值是“绕过”冻结对象的一种方法,但最终都是
obj!=tempObj
-它们的签名不再相同。但是,冻结的对象可以删除!!因此,这是目前可以接受的解决方案。克隆冻结对象&分配给同一引用,然后删除冻结对象将使我们回到旧状态,唯一的缺点是手动克隆它。当然我们把原来的弄丢了。@vivek_-nk不,不一样了。新变量具有相同的名称并不意味着它是相同的引用(指针地址)。您重写了冻结的
obj
,但仅在本地范围内。p、 我个人喜欢对象不能解冻。这有一个缺点,那就是创建和分配更多的内存,如果这是一个动画的每一帧都发生的事情
Object.freeze = function(obj) { return obj; }; // just return the original object
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);
};
const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
//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