Opposite of Object.freeze or Object.seal in JavaScript

前端 未结 9 1310
无人共我
无人共我 2020-12-02 21:41

What is the opposite of Object.freeze or Object.seal? Is there a function that has a name such as detach?

相关标签:
9条回答
  • 2020-12-02 22:32

    I think you can do, using some tricks:

    • First create a duplicate temporary variable of original object
    • then set the original variable to undefined
    • the reset the value of it from the temporary.

    Code here:

    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
    

    Note: Keep one thing in mind, don't do tempObj = obj, then it won't work because tempObj is also frozen there.

    Fiddle here: http://jsfiddle.net/mpSYu/

    0 讨论(0)
  • 2020-12-02 22:32

    You can't unfreeze a frozen object.

    You can however make it so pesky libraries can't freeze anything in the future, by overriding the Object.freeze method to be a no-op:

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

    In most cases this is enough. Just run the code above before the library is loaded, and it can no longer freeze anything. ; )


    EDIT: Some libraries, such as immer@7.0.7, have issues unless Object.isFrozen(obj) returns true after Object.freeze(obj) is called.

    The below is thus a safer way of blocking object-freezing: (the primitive checks are because WeakSet errors if you pass in primitives)

    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);
    };
    
    0 讨论(0)
  • 2020-12-02 22:36

    A little late to the party, but you can also create an object in a mutable variable (let), and reassign the original object to the variable when you need to reset it.

    For example:

    let obj = { objProp: "example" };
    
    if (condition) {
        Object.freeze(obj);
    }
    else {
        obj = { objProp: "example" };
    }
    
    0 讨论(0)
  • 2020-12-02 22:38

    Tested in FF 52:

    As far as the frozen-object's (symbolic) 'parent'-object (where it is symbolically referenced by, beside/apart from other symbolic references in other parts of code to the same object) is NOT FROZEN (like window), one can delete it nonetheless by the delete-operator, - like:

    delete window.tinymce;

    even if window.tinymce had been frozen BEFORE by Object.freeze(window.tinymce); (otherwise the 'parent' would become some kind of "frozen" itself, as containing a non-destroyable object-reference, that would make the symbol of the NOT-frozen parent un-deletable ...)

    As far as one has a copy/clone/reconstruction/own version/ of the original object already made before deletion/removal, which got rid/has none/ of the original restrictions (frozen, extensibility, configurability, writeability and so on), one can put/assign a reference to that copy/clone/reconstruction/own version/ to the original symbolic place, - like that way:

    window.tinymce = the_copy_clone_reconstruction_own_version_object;

    Make sure to have that "copy_clone_reconstruction_own_version_object" in the global scope for not being dropped after Your workaround-code has finished! [Actually the object itself should be dropped/it's memory freed/ just and only when the very last reference to it has been removed from any scope, - some time later, due to-garbage collection, but I'm not sure about the precedence higher than the 'function finished - drop all local vars']

    NOT tested: Other symbolic references MAY point to the original, frozen/restricted, object furthermore, - like something, which was set as

    myobj.subobj=window.tinymce;

    before Your operations began.

    Stuff like that (myobj.subobj) will probably (give it a try!) furthermore point to the frozen original (?).

    next notion: NOT tested!

    What about to use the 'proxy'-feature to wrap value-get/-set and other behaviour (functions, ...) of a frozen/sealed or otherwise restricted (extensibility, ...) object? Created at GLOBAL scope like p = new Proxy(target, handler); or window.p = new Proxy(target, handler);
    // where target is the object to wrap for interception/hooking/monitoring, as for instance "window.tinymce"

    The mdn-doc for the proxy-topic says, that restrictions (frozen, ...) of the wrapped object are kept regarded, but that could refer to the core-/original-object itself (wrapped by the proxy) and might eventually NOT refer to the mimic made by the proxy ...

    Scope-rules might apply as mentioned above ...

    0 讨论(0)
  • 2020-12-02 22:41

    There is no way to do this, once an object has been frozen there is no way to unfreeze it.

    Source

    Freezing an object is the ultimate form of lock-down. Once an object has been frozen it cannot be unfrozen – nor can it be tampered in any manner. This is the best way to make sure that your objects will stay exactly as you left them, indefinitely

    0 讨论(0)
  • 2020-12-02 22:41

    You can unfreeze an array by using spread operator.

    //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 
    
    0 讨论(0)
提交回复
热议问题