对JS或其语法不是新手,但有时候,语言的语义有时让我感到难过。在今天的工作中,一位同事提到了这一点:
var a = b = [];
与
不同var a = [], b = [];
或
var a = []; var b = [];
因为第一个版本实际上将对空数组的引用分配给a和b。我不能完全接受这一点,但我不确定。你们都在想什么?
答案 0 :(得分:40)
是的,他们不一样。 var a = b = []
相当于
var a;
b = [];
a = b;
不仅a
和b
都被赋予了相同的值(对同一个空数组的引用),b
根本没有被声明。在ECMAScript 5及更高版本的strict mode中,这将抛出ReferenceError
;否则,除非范围中已存在变量b
,否则b
将作为全局对象的属性静默创建,并且与代码所在的全局变量类似,即使在函数内部也是如此。这不好。
你可以很容易地看到这一点:
(function() {
var a = b = [];
})();
window.console.log(b); // Shows []
答案 1 :(得分:9)
你的同事是对的:
var a = b = [];
a.push('something');
console.log(b); // outputs ["something"]
但:
var a = [], b = [];
a.push('something');
console.log(b); // outputs []
答案 2 :(得分:4)
你的同事是对的。第一个语句创建一个新的空数组。然后,将对该数组的引用分配给b。然后,将相同的引用(它是赋值表达式的结果)赋给a。所以a和b引用相同的数组。
在所有其他情况下,您创建两个单独的数组。
顺便说一下:这种行为很常见,并且在所有基于C语言的编程语言中都是相同的。所以这不是特定于JavaScript的。
答案 3 :(得分:3)
第一个示例b
是对a
的引用,b
成为全局变量,可以从任何地方访问(并且它会替换可能已经存在的任何b
变量存在于全球范围内)。
答案 4 :(得分:1)
要实现此目的,您需要从链接赋值中拆分var
声明(请参阅:
http://davidshariff.com/blog/chaining-variable-assignments-in-javascript-words-of-caution/)。
E.g。
var one = 1, two = 2;
one = two = 3; /* Now both equal 3 */
但如果你按照你所描述的那样(本例中为var one = two = 3;
)two
泄漏到全局空间,而one
在本地范围内声明。
答案 5 :(得分:0)
补充已提供的答案。 ref赋值与值赋值不同
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]
现在我们已经解决了2两个,你的问题也提到了linting,这是“漂亮的代码”(不是功能)的做法。事实上,JSHint has deprecated all their "pretty code rules"
话虽如此,我通常使用以下风格.-
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