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
注:1つのことに留意してください。tempObj = obj
、それはtempObj
もそこでフリーズされているので動作しません。
ここでフィドル: http://jsfiddle.net/mpSYu/
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.freezeメソッドをno-opにオーバーライドすることで、厄介なライブラリが将来何もフリーズできないようにすることができます。
Object.freeze = function(obj) { return obj; }; // just return the original object
ほとんどの場合、これで十分です。ライブラリをロードする前に上記のコードを実行するだけで、何もフリーズできなくなります。 ; )
オブジェクトをフリーズ解除(解凍)することはできませんが、オブジェクトが単純にプリミティブ(関数またはクラスなし)のコレクションである場合、次のようにオブジェクトの解凍されたクローンを取得できます。
const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
FF 52でテスト済み:
凍結されたオブジェクトの(シンボリックな)「親」オブジェクト(同じオブジェクトへのコードの他の部分の他のシンボリック参照とは別に、シンボリックに参照される)は、FROZEN(ウィンドウなど)ではありません。それにもかかわらず、delete-operatorで削除します-など:
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);のようなGLOBALスコープで作成されました;またはwindow.p = new Proxy(target、handler);
// targetは、インターセプト/フック/監視のためにラップするオブジェクトです。たとえば、「window.tinymce」
プロキシトピックのmdn-docには、ラップされたオブジェクトの制限(凍結など)は考慮されますが、それはコア/元のオブジェクト自体(プロキシによってラップされる)を参照でき、最終的にはプロキシによって作成された模倣を参照しないでください...
上記のようにスコープルールが適用される場合があります...
私はこれを試しましたが、うまく機能しています
let obj = {name:'Trickester', age:25}
Object.freeze(obj)
let newObj = obj
obj = null
obj = newObj
//make whatever changes you
私もその問題を発行しました。それを修正するために、JavaScript JSON APIを使用してオブジェクトをフリーズ解除しました:const unfreezeObject = JSON.parse(JSON.stringify(freezeObject))
。その後、必要なすべての突然変異を行いました。
スプレッド演算子を使用して配列を凍結解除できます。
//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