Considerate le seguenti dichiarazioni:incatenato assegnazione e riferimento circolare in JavaScript
var foo = {n: 1};
foo.bar = foo = {n: 2};
Può spiegare perché foo.bar
è undefined
invece di essere foo
?
Considerate le seguenti dichiarazioni:incatenato assegnazione e riferimento circolare in JavaScript
var foo = {n: 1};
foo.bar = foo = {n: 2};
Può spiegare perché foo.bar
è undefined
invece di essere foo
?
Durante l'esecuzione dell'operatore di assegnazione, JS valuta prima la parte sinistra. Quindi questo
foo.bar = foo = {n: 2};
viene interpretato come
valutare foo.bar
. Questo restituisce un riferimento {base: Object {n:1}, property:bar}
.
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}
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>")
È stato modificato l'oggetto a cui si riferisce foo
. Non c'è bar
in {n: 2}
. Cosa ti aspettavi?
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
e, 'foo2.bar === foo1; // true' –
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.
l'oggetto originale 'foo' ce l'ha, non quello nuovo. –
Cosa succede se hai fatto 'foo.bar = foo = {bar: 2}'? Che funzioni. – Luminous
@Luminoso no no; 'foo.bar === 2', non' {n: 1} '(' foo') – Mathletics