2013-10-31 13 views
13

Questo esempio crea un oggetto, lo congela e quindi crea un nuovo oggetto dall'oggetto congelato. Se il secondo oggetto tenta di modificare la proprietà test, non può. Resta congelato con il valore del primo oggetto di 10.Creazione di nuovi oggetti da oggetti padre congelati

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

Ecco le mie domande:

E` second.test una nuova proprietà in un nuovo oggetto, o è solo un riferimento alla proprietà nel congelato primo oggetto?
È possibile utilizzare il valore congelato first.test come valore predefinito, ma lasciare che sia second.test sovrascriverlo se necessario?

La ragione per cui chiedo è perché voglio rendere immutabile un oggetto base come modello con valori predefiniti e quindi usarlo per creare nuovi oggetti che posso personalizzare. Qual è l'approccio migliore per questo?

Grazie!

risposta

11

second è di fatto un nuovo oggetto, con first è il prototipo di second. Il motivo per cui

second.test = 20; 

non funziona è perché al momento di assegnazione, cercherà le impostazioni del prototipo (cioè configurable, enumerable, writable, [[Extensible]]) e non assegnare all'istanza se uno di questi sono false . Per assegnare direttamente all'istanza, dovrete usare Object.defineProperty su second:

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

Nel tuo caso second è un riferimento a first (come si presume). Una soluzione sarebbe quella di clonare il tuo oggetto. Non v'è alcun costruire in modo per clonare gli oggetti - dovete farlo da soli, ecco come (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; 
} 

quindi si utilizza in questo modo:

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

Usa 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

Pretty case case, ma si noti che questo non funziona se l'oggetto congelato contiene riferimenti ad altri oggetti congelati e si tenta di sovrascrivere _their_ properties. Ancora una tecnica piuttosto utile per semplici strutture di dati, solo a nessuno viene l'idea che sia un modo infallibile per creare immutabili. – Dtipson

Problemi correlati