在Javascript中分配多个变量到相同的值?

我在一个JavaScript文件中初始化了全局作用域中的几个变量:

var moveUp, moveDown, moveLeft, moveRight;
var mouseDown, touchDown;

我需要把所有这些变量都设为false。这是我目前拥有的代码:

moveUp    = false;
moveDown  = false;
moveLeft  = false;
moveRight = false
mouseDown = false;
touchDown = false;

是否有任何方法,我可以设置所有这些变量的相同值在一行代码,或者是代码我目前有最好的方式来做到这一点?

257415 次浏览

没有什么能阻止你去做

moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

检查这个例子

var a, b, c;
a = b = c = 10;
console.log(a + b + c)

没有什么能阻止你这样做,但是坚持住!

这里有一些陷阱。在Javascript中赋值是从右向左的,所以当你写:

var moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

它有效地翻译为:

var moveUp = (moveDown = (moveLeft = (moveRight = (mouseDown = (touchDown = false)))));

这句话的意思是:

var moveUp = (window.moveDown = (window.moveLeft = (window.moveRight = (window.mouseDown = (window.touchDown = false)))));

无意间,您创建了5个全局变量——我很确定您不想这样做。

注意:我上面的例子假设你在浏览器中运行你的代码,因此window。如果你在不同的环境中,这些变量将附加到该环境的任何全局上下文(即,在Node.js中,它将附加到global,这是该环境的全局上下文)。

现在你可以先声明所有的变量,然后将它们赋值给相同的值,这样就可以避免这个问题。

var moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown;
moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;

长话短说,两种方法都可以很好地工作,但是第一种方法可能会在代码中引入一些有害的错误。如果不是绝对必要,不要在全局名称空间中使用局部变量。


旁注:正如评论中所指出的(这不仅仅是在这个问题的情况下),如果所讨论的复制值不是一个基本值,而是一个对象,您最好了解按值复制和按引用复制。每当分配对象时,复制对象的引用而不是实际对象。所有变量仍然指向同一个对象,因此一个变量的任何更改都将反映到其他变量中,如果您的目的是复制对象值而不是引用,则会使您非常头痛。

当尝试将多个变量初始化为相同的值时,还有另一个选项不会引入全局陷阱。这条路是否比远路更可取,这是一个判断。它可能会更慢,并且可能更具可读性。在您的具体情况下,我认为长距离可能更具可读性和可维护性,而且速度更快。

其他方法使用解构的任务

let [moveUp, moveDown,
moveLeft, moveRight,
mouseDown, touchDown] = Array(6).fill(false);


console.log(JSON.stringify({
moveUp, moveDown,
moveLeft, moveRight,
mouseDown, touchDown
}, null, '  '));


// NOTE: If you want to do this with objects, you would be safer doing this
let [obj1, obj2, obj3] = Array(3).fill(null).map(() => ({}));
console.log(JSON.stringify({
obj1, obj2, obj3
}, null, '  '));
// So that each array element is a unique object


// Or another cool trick would be to use an infinite generator
let [a, b, c, d] = (function*() { while (true) yield {x: 0, y: 0} })();
console.log(JSON.stringify({
a, b, c, d
}, null, '  '));


// Or generic fixed generator function
function* nTimes(n, f) {
for(let i = 0; i < n; i++) {
yield f();
}
}
let [p1, p2, p3] = [...nTimes(3, () => ({ x: 0, y: 0 }))];
console.log(JSON.stringify({
p1, p2, p3
}, null, '  '));

这允许你将一组varletconst变量初始化为一行上相同的值,所有这些变量都具有相同的预期作用域。

引用:

将变量放入数组中,并使用for循环将相同的值赋给多个变量。

  myArray[moveUP, moveDown, moveLeft];


for(var i = 0; i < myArray.length; i++){


myArray[i] = true;


}

您所列出的原始变量可以在使用解构赋值的短代码行中声明并赋值给相同的值。关键字letconstvar都可以用于这种类型的赋值。

let [moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown] = Array(6).fill(false);

我个人总是尽量避免var,总是使用letconst,我从发生的错误和大多数最佳实践建议中学到了这一点,所以下面在评论中提到,但更准确地说:

function good() {
let a;
let b;
let c;
let d;
a = b = c = d = 'hello';
console.log(d);
}


function bad() {
//only the first variable is declared as local
let a = b = c = d = 'bye';
console.log(d)
}


let a;
let d;


good();
bad();


//expected undefined
console.log(a);


//expected bye
console.log(d);