与JavaScript中的Object.freeze或Object.seal相反

时间:2013-10-10 10:29:47

标签: javascript locking freeze

Object.freezeObject.seal的反面是什么?是否有一个具有诸如detach等名称的函数?

11 个答案:

答案 0 :(得分:73)

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

Source

  

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

答案 1 :(得分:14)

我认为你可以做一些技巧:

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

此处的代码:

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/

答案 2 :(得分:7)

有线解决方案:)

 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]

答案 3 :(得分:2)

您无法解冻冻结的物体。

但是,你可以通过将Object.freeze方法重写为无操作来使得讨厌的库不能在将来冻结任何东西:

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

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

答案 4 :(得分:1)

在FF 52中测试:

至于冻结对象(符号)' parent' -object(其中它被符号引用,旁边/除了代码的其他部分中的其他符号引用)对象)不是冷冻(就像窗口一样),但是可以通过删除操作符删除它,如:

删除window.tinymce;

即使window.tinymce已经被Object.freeze(window.tinymce)冻结了; (否则'父母将成为某种"冻结"本身,因为包含不可破坏的对象引用,这将使未冻结的父对象的符号不可删除...)

就删除/删除之前已经创建的原始对象的复制/克隆/重建/自己的版本/已经删除/没有原始限制(冻结,可扩展性,可配置性,可写性等等) on),可以将该副本/克隆/重建/自己的版本/的引用/分配给原始的符号位置, - 就像这样:

window.tinymce = the_copy_clone_reconstruction_own_version_object;

确保拥有" copy_clone_reconstruction_own_version_object"在您的变通方法代码完成后未被删除的全局范围! [实际上,对象本身应该被删除/它的内存被释放/只是当它的最后一个引用被从任何范围中移除时 - 一段时间之后,由于垃圾收集,但我'我不确定优先级高于'功能完成 - 删除所有本地变量']

未经测试: 其他符号引用可以指向原始的,冻结的/受限制的对象,例如,设置为

的东西

myobj.subobj = window.tinymce;

在你的行动开始之前。

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

下一个概念: 未经测试!

如何使用' proxy' -feature来包装value-get / -set和其他行为(函数,......)的冻结/密封或其他限制(可扩展性,...... )对象? 创建于GLOBAL范围之类的  p =新代理(目标,处理程序); 要么  window.p =新代理(目标,处理程序);
//其中target是用于拦截/挂钩/监视的对象,例如" window.tinymce"

代理主题的mdn-doc说,包装对象的限制(冻结,...)被认为是,但是可以引用core- / original-object本身(由代理包装)并且最终可能不会引用代理人制作的模仿......

范围规则可能适用于上述......

答案 5 :(得分:1)

你无法解冻(解冻)一个对象,但如果该对象只是一个基元的集合(没有函数或类),你就可以得到一个解冻的对象克隆:

fun isNotificationAllowed(context: Context): Boolean {
    return if (isOOrLater()) {
        areNotificationsEnabled(context) and isChannelDisabled(context)
    } else {
        areNotificationsEnabled(context)
    }
}

private fun areNotificationsEnabled(context: Context) =
    NotificationManagerCompat.from(context).areNotificationsEnabled()

@RequiresApi(api = Build.VERSION_CODES.O)
private fun isChannelDisabled(context: Context): Boolean{
    val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channel = notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID)
    return channel.importance != NotificationManager.IMPORTANCE_NONE
}

private fun isOOrLater() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

我也是问题。为了解决这个问题,我使用了JavaScript JSON API来解冻我的对象:<plugin name="cordova-plugin-battery-status" source="npm" spec="~1.1.1" /> <plugin name="cordova-plugin-camera" source="npm" spec="~2.1.1" /> <plugin name="cordova-plugin-media-capture" source="npm" spec="~1.2.0" /> <plugin name="cordova-plugin-console" source="npm" spec="~1.0.2" /> <plugin name="cordova-plugin-contacts" source="npm" spec="~2.0.1" /> <plugin name="cordova-plugin-device" source="npm" spec="~1.1.1" /> <plugin name="cordova-plugin-device-motion" source="npm" spec="~1.2.0" /> <plugin name="cordova-plugin-device-orientation" source="npm" spec="~1.0.2" /> <plugin name="cordova-plugin-dialogs" source="npm" spec="~1.2.0" /> <plugin name="cordova-plugin-file" source="npm" spec="~4.1.1" /> <plugin name="cordova-plugin-file-transfer" source="npm" spec="~1.5.0" /> <plugin name="cordova-plugin-geolocation" source="npm" spec="~2.1.0" /> <plugin name="cordova-plugin-globalization" source="npm" spec="~1.0.3" /> <plugin name="cordova-plugin-inappbrowser" source="npm" spec="~1.3.0" /> <plugin name="cordova-plugin-media" source="npm" spec="~2.2.0" /> <plugin name="cordova-plugin-network-information" source="npm" spec="~1.2.0" /> <plugin name="cordova-plugin-splashscreen" source="npm" spec="~3.2.1" /> <plugin name="cordova-plugin-statusbar" source="npm" spec="~2.1.2" /> <plugin name="cordova-plugin-vibration" source="npm" spec="~2.1.0" /> <plugin name="cordova-plugin-whitelist" source="npm" spec="~1.2.1" /> <plugin name="cordova-plugin-x-socialsharing" source="npm" /> 。之后,我做了我需要的所有突变。

答案 8 :(得分:0)

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

例如:

let obj = { objProp: "example" };

if (condition) {
    Object.freeze(obj);
}
else {
    obj = { objProp: "example" };
}

答案 9 :(得分:0)

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

考虑到这一点,这是我根据 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";

答案 10 :(得分:-2)

我尝试了这个,它工作正常

let obj = {name:'Trickester', age:25}
 Object.freeze(obj)
 let newObj = obj
 obj = null
 obj = newObj
 //make whatever changes you