Was ist das Gegenteil von Object.freeze
oder Object.seal
? Gibt es eine Funktion mit einem Namen wie "Trennen"?
Was ist das Gegenteil von Object.freeze
oder Object.seal
? Gibt es eine Funktion mit einem Namen wie "Trennen"?
Antworten:
Es gibt keine Möglichkeit, dies zu tun. Sobald ein Objekt eingefroren wurde, gibt es keine Möglichkeit, es wieder einzufrieren.
Das Einfrieren eines Objekts ist die ultimative Form der Sperrung. Sobald ein Objekt eingefroren wurde, kann es nicht mehr eingefroren oder in irgendeiner Weise manipuliert werden. Dies ist der beste Weg, um sicherzustellen, dass Ihre Objekte auf unbestimmte Zeit genau so bleiben, wie Sie sie verlassen haben
Object.freeze(obj); thirdPartyRoutine(obj); Object.unfreeze(obj); /*continue using obj*/
Ich denke, Sie können dies mit einigen Tricks tun:
Code hier:
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
Hinweis: Beachten Sie eines, tun Sie es nicht tempObj = obj
, dann funktioniert es nicht, da tempObj
es dort auch eingefroren ist.
Geige hier: http://jsfiddle.net/mpSYu/
obj != tempObj
sind ihre Signaturen nicht mehr dieselben.
obj
, jedoch nur im lokalen Bereich. ps Ich persönlich mag es, dass Objekte nicht ungefroren werden können.
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.assign
bessere Option. Allerdings ist eine Kopie / ein Klon auch nicht das, wonach ich suche
Sie können ein eingefrorenes Objekt nicht auftauen.
Sie können es jedoch so gestalten, dass lästige Bibliotheken in Zukunft nichts mehr einfrieren können, indem Sie die Object.freeze-Methode als No-Op überschreiben:
Object.freeze = function(obj) { return obj; }; // just return the original object
In den meisten Fällen reicht dies aus. Führen Sie einfach den obigen Code aus, bevor die Bibliothek geladen wird, und sie kann nichts mehr einfrieren. ;; )
BEARBEITEN : Einige Bibliotheken, z. B. immer@7.0.7
, haben Probleme, es sei denn, die Object.isFrozen(obj)
Rückgabe erfolgt true
nach dem Object.freeze(obj)
Aufruf.
Das Folgende ist somit eine sicherere Methode zum Blockieren des Einfrierens von Objekten: (Die primitiven Überprüfungen sind auf WeakSet
Fehler zurückzuführen, wenn Sie Primitive übergeben.)
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);
};
Object.freeze
funktioniert aus einem bestimmten Grund so.
Sie können ein Objekt nicht auftauen (auftauen), aber wenn das Objekt einfach eine Sammlung von Grundelementen ist (keine Funktionen oder Klassen), können Sie einen aufgetauten Klon des Objekts wie folgt erhalten:
const unfrozenObj = JSON.parse(JSON.stringify(frozenObj));
Getestet in FF 52:
Soweit das (symbolische) 'Eltern'-Objekt des eingefrorenen Objekts (wo es symbolisch durch, neben / abgesehen von anderen symbolischen Verweisen in anderen Teilen des Codes auf dasselbe Objekt referenziert wird) NICHT GEFROREN ist (wie Fenster), kann man lösche es trotzdem durch den Löschoperator, - wie:
window.tinymce löschen;
selbst wenn window.tinymce VORHER von Object.freeze (window.tinymce) eingefroren wurde; (Andernfalls würde das 'Elternteil' selbst zu einer Art "eingefrorenem" Element, das eine nicht zerstörbare Objektreferenz enthält und das Symbol des NICHT eingefrorenen Elternteils nicht mehr löschbar macht ...)
Soweit man eine Kopie / Klon / Rekonstruktion / eigene Version / des Originalobjekts bereits vor dem Löschen / Entfernen erstellt hat, die keine / der ursprünglichen Einschränkungen (eingefroren, Erweiterbarkeit, Konfigurierbarkeit, Beschreibbarkeit usw.) beseitigt hat, man kann einen Verweis auf diese Kopie / Klon / Rekonstruktion / eigene Version / auf den ursprünglichen symbolischen Ort setzen / zuweisen - so:
window.tinymce = the_copy_clone_reconstruction_own_version_object;
Stellen Sie sicher, dass "copy_clone_reconstruction_own_version_object" im globalen Bereich vorhanden ist, damit es nicht gelöscht wird, nachdem Ihr Workaround-Code beendet wurde! [Eigentlich sollte das Objekt selbst gelöscht werden / es wird Speicher freigegeben / nur und nur dann, wenn der allerletzte Verweis darauf aus einem Bereich entfernt wurde - einige Zeit später aufgrund der Speicherbereinigung, aber ich bin mir nicht sicher, welche Priorität es hat höher als die 'Funktion beendet - alle lokalen Variablen löschen']
NICHT getestet: Andere symbolische Verweise KÖNNEN außerdem auf das ursprüngliche, eingefrorene / eingeschränkte Objekt verweisen - wie etwas, das als festgelegt wurde
myobj.subobj = window.tinymce;
bevor Ihre Operationen begannen.
Solche Sachen (myobj.subobj) werden wahrscheinlich (probieren Sie es aus!) Weiterhin auf das gefrorene Original (?) Zeigen.
nächste Vorstellung: NICHT getestet!
Was ist mit der 'Proxy'-Funktion, um Value-Get / Set und anderes Verhalten (Funktionen, ...) eines eingefrorenen / versiegelten oder anderweitig eingeschränkten (Erweiterbarkeit, ...) Objekts zu verpacken? Erstellt im GLOBAL-Bereich wie p = neuer Proxy (Ziel, Handler); oder window.p = neuer Proxy (Ziel, Handler);
// wobei target das Objekt ist, das zum Abfangen / Einhaken / Überwachen umbrochen werden soll, wie zum Beispiel "window.tinymce"
Das mdn-doc für das Proxy-Thema besagt, dass Einschränkungen (eingefroren, ...) des umschlossenen Objekts beibehalten werden, die sich jedoch auf das Core- / Original-Objekt selbst (vom Proxy umschlossen) beziehen und möglicherweise auch NICHT auf die Nachahmung durch den Proxy verweisen ...
Geltungsbereichsregeln können wie oben erwähnt gelten ...
Ich habe dieses Problem auch gelöst. Um dies zu beheben, habe ich die JavaScript-JSON-API verwendet, um mein Objekt freizugeben : const unfreezeObject = JSON.parse(JSON.stringify(freezeObject))
. Danach habe ich alle Mutationen gemacht, die ich brauchte.
{ ...item }
möglicherweise nur eine flache Kopie erforderlich.
Ein wenig zu spät zur Party, aber Sie können auch ein Objekt in einer veränderlichen Variablen ( let
) erstellen und das ursprüngliche Objekt der Variablen neu zuweisen, wenn Sie es zurücksetzen müssen.
Zum Beispiel:
let obj = { objProp: "example" };
if (condition) {
Object.freeze(obj);
}
else {
obj = { objProp: "example" };
}
Sie können ein Array mit dem Spread-Operator auftauen.
//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