2015-08-07 20 views

risposta

12

Durante l'esecuzione dell'operatore di assegnazione, JS valuta prima la parte sinistra. Quindi questo

foo.bar = foo = {n: 2}; 

viene interpretato come

  1. valutare foo.bar. Questo restituisce un riferimento {base: Object {n:1}, property:bar}.

  2. poi valutare la seconda assegnazione:

    2.1 eval foo. Restituisce un riferimento {base:<scope>, property:foo}

    2.2. eval {n:2}. Questo crea un nuovo oggetto.

    2.3 valore put: <scope>.foo = {n:2}

    2,4 ritorno {n:2}

  3. put valore al primo riferimento: {n:1}.bar = {n:2}. Questo funziona bene, ma il vecchio oggetto {n:1} non è accessibile più, dal momento che si riferisce <scope>.foo già al nuovo oggetto

Dettagli: http://ecma-international.org/ecma-262/5.1/#sec-11.13.1

Se si effettua una copia di foo prima, vedrai che più a sinistra = modifica effettivamente il vecchio oggetto:

var foo = {n:1}; 
 
var oldFoo = foo; 
 

 
foo.bar = foo = {n: 2}; 
 

 
document.write(JSON.stringify(foo) + "<br>") 
 
document.write(JSON.stringify(oldFoo) + "<br>")

0

È stato modificato l'oggetto a cui si riferisce foo. Non c'è bar in {n: 2}. Cosa ti aspettavi?

2

Quindi, quando si verifica l'assegnazione per foo.bar, il riferimento è "compilato" per foo. che lo rende l'oggetto originale.

Espandiamo un po 'il codice per renderlo più chiaro.

var foo1, foo2; 
foo1 = foo2 = {n:1}; 
foo1 === foo2; // true 
foo1.bar = foo1 = {n:2} 
foo1.bar === foo2; // false 
foo1 === foo2; // false 
+0

e, 'foo2.bar === foo1; // true' –

1

Ci sono due oggetti in gioco qui. Uno avrà una proprietà bar, l'altro non lo farà. Per mostrare questo, memorizzerò l'oggetto originale in un'altra variabile per il confronto.

var foo = {n: 1}; 
var orig = foo; 
foo.bar = foo = {n: 2}; 
console.log(foo, orig); // {n:2}, {n:1, bar: {n:2}} 

finché la linea foo.bar è fatto di esecuzione, foo contiene ancora l'oggetto originale, quindi la proprietà barra dell'oggetto originale sarà impostato al nuovo oggetto.

Problemi correlati