2013-10-31 9 views
13

In diesem Beispiel wird ein Objekt erstellt, eingefroren und anschließend ein neues Objekt aus dem eingefrorenen Objekt erstellt. Wenn das zweite Objekt versucht, die Testeigenschaft zu ändern, kann es nicht. Es bleibt eingefroren mit dem ersten Objekts Wert von 10.Erstellen von neuen Objekten aus eingefrorenen übergeordneten Objekten

//Create an object and freeze it 

var first = { 
    test: 10 
}; 
Object.freeze(first); 

//Create a second object from the first one and 
//try and change the new test property (you can't) 

var second = Object.create(first); 
second.test = 20; 
console.log(second.test); //10 

Hier sind meine Fragen:

Ist second.test eine neue Eigenschaft an einem neuen Objekt, oder ist es nur ein Verweis auf die Eigenschaft im gefrorenen erstes Objekt?
Ist es möglich, den eingefrorenen als Standardwert zu verwenden, aber second.test überschreiben, wenn es erforderlich ist?

Mein Grund für die Frage ist, weil ich ein Basisobjekt als eine Vorlage mit Standardwerten unveränderlich machen und dann verwenden möchte, um neue Objekte zu erstellen, die ich anpassen kann. Was ist der beste Ansatz dafür?

Danke!

Antwort

11

second ist in der Tat ein neues Objekt, wobei first der Prototyp second ist. Der Grund, warum

second.test = 20; 

nicht funktioniert, ist, weil bei Zuweisung, es für die Einstellungen auf dem Prototyp aussehen wird (dh configurable, enumerable, writable, [[Extensible]]) und nicht auf die Instanz zuweisen, wenn einer dieser falsch ist . Um direkt auf die Instanz zuweisen, werden Sie Object.defineProperty auf second verwenden:

var first = { 
    test: 10 
}; 
Object.freeze(first); 

var second = Object.create(first); 
Object.defineProperty(second, 'test', { value: 20, enumerable: true, configurable: true, writable: true }); 
console.log(second.test); // 20 

1:[[Put]]: the ECMAScript Specification, §8.12.5

2

In Ihrem Fall second ist ein Verweis auf first (wie Sie angenommen). Eine Lösung wäre, Ihr Objekt zu klonen. Es gibt keinen eingebauten Weg, um Objekte zu klonen - Sie können es selbst zu tun haben, ist hier, wie (source):

function clone(obj){ 
    if(obj == null || typeof(obj) != 'object') 
     return obj; 

    var temp = obj.constructor(); 

    for(var key in obj) 
     temp[key] = clone(obj[key]); 
    return temp; 
} 

Dann Sie es auf diese Weise verwenden:

var first = { 
    test: 10 
}; 
Object.freeze(first); 

// clone it into a new one 
var second = clone(first); 
second.test = 20; 
console.log(second.test); // 20 where the first is locked 
6

Verwenden Object.assign

  var first = { 
      test: 10 
     }; 
     Object.freeze(first); 

     //Create a second object from the first one and 
     //try and change the new test property (you can't) 

     var second = Object.assign({}, first, { 
      test: 20 
     }); 
     console.log(second.test); //20 
+0

Ziemlich außerhalb Fall, aber beachten Sie, dass dies immer noch nicht funktioniert, wenn das eingefrorene Objekt Verweise auf andere eingefrorene Objekte enthält, und Sie versuchen, _their_ Eigenschaften zu überschreiben. Immer noch eine ziemlich nützliche Technik für einfache Datenstrukturen, nur niemand kommt auf die Idee, dass es eine narrensichere Möglichkeit ist, immutables zu erstellen. – Dtipson

Verwandte Themen