2010-08-02 15 views
24

Non sono nuovo a JS o alla sua sintassi, ma a volte, la semantica della lingua mi ha bloccato a volte. Oggi al lavoro, un collega citato questo:In JavaScript, l'assegnazione concatenata va bene?

var a = b = []; 

non è la stessa

var a = [], b = []; 

o

var a = []; var b = []; 

rispetto alla prima versione effettivamente assegna il riferimento a un array vuoto ad una e B. Non potevo accettarlo come vero, ma non ne sono sicuro. Che cosa ne pensate?

+3

Vedi http://stackoverflow.com/questions/1758576/multiple-left-hand-assignment-with-javascript/1758912 # 1758912 –

+0

Grazie, Crescent Fresh - Non ho proprio visto quella domanda perché stavo cercando "incarichi concatenati". – JamieJag

risposta

32

Sì, non sono la stessa cosa. var a = b = [] è equivalente a

var a; 
b = []; 
a = b; 

Non soltanto sia a e b ottenere assegnato lo stesso valore (un riferimento allo stesso array vuoto), b è dichiarato non affatto. In strict mode in ECMAScript 5 e versioni successive, verrà generato un numero ReferenceError; altrimenti, a meno che non sia già presente una variabile b nello scope, b viene creato automaticamente come una proprietà dell'oggetto globale e agisce in modo simile a una variabile globale, ovunque sia il codice, anche all'interno di una funzione. Che non va bene

Si può vedere questo abbastanza facilmente:

(function() { 
    var a = b = []; 
})(); 

window.console.log(b); // Shows [] 
+1

Non ho visto immediatamente che b è una variabile globale, grazie! – JamieJag

+4

+1 Un altro motivo per evitare un'assegnazione a un riferimento irrisolvibile è che su ES5, in modalità rigorosa, verrà lanciato un 'ReferenceError'. – CMS

4

Il tuo collega ha ragione. La prima istruzione crea una nuova matrice vuota. Quindi, un riferimento a questo array è assegnato a b. Quindi, lo stesso riferimento (che è il risultato dell'espressione di assegnazione) viene assegnato a a. Quindi a e b si riferiscono allo stesso array.

In tutti gli altri casi, vengono creati due singoli array.

A proposito: questo comportamento è abbastanza comune ed è lo stesso in tutti i linguaggi di programmazione basati su C. Quindi questo non è specifico di JavaScript.

+0

Grazie per la tua risposta, Tobias, e anche per sottolineare la comunanza in tutte le lingue basate su C. – JamieJag

+0

Questo può essere testato con gli array in JS: '[" dog "] === [" dog "];' restituisce false, ma 'var a = b = [" dog "]; a === b; 'restituisce true. – b00t

9

Il suo collega ha ragione:

var a = b = []; 
a.push('something'); 
console.log(b);   // outputs ["something"] 

ma:

var a = [], b = []; 
a.push('something'); 
console.log(b);   // outputs [] 
3

Con il primo esempio b è un riferimento a a, e b diventa una variabile globale, accessibile da qualsiasi luogo (e sostituisce qualsiasi b variabile che può già esistere nell'ambito globale).

0

Per completare le risposte già fornite.assegnazioni ref sono diverse dalle assegnazioni di valori

var x = y = 3; // by value 
y++; // 4 
x; // 3 

var a = b = []; // by ref 
b.push(1); // [1]; 
a; // [1] 
a; = []; 
a.push(2); // [2]; 
b; // [1] 

Ora che abbiamo affrontato 2 due, la tua domanda fa anche riferimento al rilascio di fibre, che è la pratica di "pretty codice" (non funzionante). In realtà, JSHint has deprecated all their "pretty code rules"

Ciò premesso, io di solito uso il seguente style.-

var a, b, c, // first row all unassigned 
    x = 1, // 1 row per assigned 
    y = 2, 
    list = [ 
     'additional', 
     'indentation' 
    ], 
    obj = { 
     A: 'A', 
     B: 'B' 
    }; 
var z = y +2; // created a new `var` cluster since it uses a var from the previous