2010-08-02 25 views
24

No soy nuevo en JS o su sintaxis, pero a veces, la semántica del lenguaje me ha dejado perplejo a veces. En el trabajo actual, un colega mencionó esto:En JavaScript, ¿la asignación encadenada está bien?

var a = b = []; 

no es lo mismo que

var a = [], b = []; 

o

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

desde la primera versión realmente asigna la referencia a una matriz vacía a una y B. No podía aceptar esto como cierto, pero no estoy seguro. ¿Qué piensan todos ustedes?

+3

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

+0

Gracias, Crescent Fresh: no pude ver esa pregunta porque estaba buscando "asignación encadenada". – JamieJag

Respuesta

32

Sí, no son lo mismo. var a = b = [] es equivalente a

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

No sólo hacer las dos a y b se les asigna el mismo valor (una referencia a la misma matriz vacía), b no se declara en absoluto. En strict mode en ECMAScript 5 y posterior, arrojará un ReferenceError; de lo contrario, a menos que ya haya una variable b en alcance, b se crea silenciosamente como una propiedad del objeto global y actúa de forma similar a una variable global, donde sea que esté el código, incluso dentro de una función. Lo cual no es bueno

Esto se puede ver con bastante facilidad:

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

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

No vi de inmediato que b sea una variable global, ¡gracias! – JamieJag

+4

+1 Otra razón para evitar una asignación a una referencia no resuelta es que en ES5, en modo estricto, se lanzará un 'ReferenceError'. – CMS

4

Su colega tiene razón. La primera declaración crea una nueva matriz vacía. Luego, se asigna una referencia a esta matriz a b. Luego, la misma referencia (que es el resultado de la expresión de asignación) se asigna a a. Entonces a y b se refieren a la misma matriz.

En todos los demás casos, crea dos matrices individuales.

Dicho sea de paso: Este comportamiento es bastante común y es el mismo en todos los lenguajes de programación basados ​​en C. Entonces esto no es específico de JavaScript.

+0

Gracias por su respuesta, Tobias, y también por señalar las características comunes en todos los lenguajes basados ​​en C. – JamieJag

+0

Esto se puede probar con matrices en JS: '[" dog "] === [" dog "];' devuelve false, pero 'var a = b = [" dog "]; a === b; 'devuelve verdadero. – b00t

9

Su colega tiene razón:

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

pero:

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

Con el primer ejemplo b es una referencia a a y b se convierte en una variable global, accesible desde cualquier lugar (y que sustituye a cualquier variable b que ya pueda existir en el alcance global).

0

Para complementar las respuestas ya proporcionadas.asignaciones árbitro son diferentes de asignaciones de valores

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] 

Ahora que hemos abordado 2 dos, su pregunta también hace referencia a la formación de pelusas, que es la práctica de "código bastante" (no funcional). De hecho, JSHint has deprecated all their "pretty code rules"

Eso se ha dicho, que suelen utilizar los siguientes 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 
Cuestiones relacionadas