在Javascript中将多个变量分配给相同的值

155 javascript

我在JavaScript文件中初始化了全局范围内的几个变量:

var moveUp, moveDown, moveLeft, moveRight;
var mouseDown, touchDown;
Run Code Online (Sandbox Code Playgroud)

我需要将所有这些变量设置为false,这是我目前拥有的代码:

moveUp    = false;
moveDown  = false;
moveLeft  = false;
moveRight = false
mouseDown = false;
touchDown = false;
Run Code Online (Sandbox Code Playgroud)

有什么方法可以将所有这些变量设置为一行代码中的相同值,或者我现在有最好的方法来执行此操作的代码

kar*_*ikr 255

没有什么能阻止你做

moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;
Run Code Online (Sandbox Code Playgroud)

检查此示例

var a, b, c;
a = b = c = 10;
console.log(a + b + c)
Run Code Online (Sandbox Code Playgroud)

  • 是的,如果使用对象执行此操作,则所有变量都将是对象的别名.IE`函数MyObj(){this.x = 1} var a,b; a = b = new MyObj(); ++ ax`也会增加`bx`属性. (25认同)
  • 范围问题!http://stackoverflow.com/questions/1758576/multiple-left-hand-assignment-with-javascript (25认同)
  • 在按照建议的方式分配值时,您可能想要评论行为将如何区分基本类型和引用类型. (12认同)
  • 我想说如果你没有全局确定赋值左边的所有变量,请不要使用这种方法 (4认同)
  • 正如@doublejosh所说,有一些范围问题你没有解决. (2认同)

Gov*_*Rai 66

没有什么可以阻止你做上述事情,但坚持!

有一些陷阱.Javascript中的赋值是从右到左,所以当你写:

var moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;
Run Code Online (Sandbox Code Playgroud)

它有效地转化为:

var moveUp = (moveDown = (moveLeft = (moveRight = (mouseDown = (touchDown = false)))));
Run Code Online (Sandbox Code Playgroud)

这有效地转化为:

var moveUp = (window.moveDown = (window.moveLeft = (window.moveRight = (window.mouseDown = (window.touchDown = false)))));
Run Code Online (Sandbox Code Playgroud)

不经意间,你刚刚创建了5个全局变量 - 我很确定你不想这样做.

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

现在,您可以先声明所有变量,然后将它们分配给相同的值,这样就可以避免出现问题.

var moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown;
moveUp = moveDown = moveLeft = moveRight = mouseDown = touchDown = false;
Run Code Online (Sandbox Code Playgroud)

简而言之,两种方式都可以正常工作,但第一种方式可能会在您的代码中引入一些有害的错误.如果不是绝对必要的话,不要犯下使用局部变量乱扔全局命名空间的罪.


旁注:正如评论中指出的那样(这不仅仅是在这个问题的情况下),如果复制的值不是原始值而是对象,您最好知道按值复制与按引用复制.每当分配对象时,都会复制对象的引用而不是实际对象.所有变量仍将指向同一个对象,因此一个变量中的任何更改都将反映在其他变量中,如果您的目的是复制对象值而不是引用,则会让您头疼.

  • @ElisByberi 感谢您的评论。你没有错。我的回答的目标是解决已接受答案中的第一句话。对此,我的回答进一步明确了这一点。 (3认同)
  • @P-RAD 只有使用 let 声明的第一个变量才会存在于封闭范围中。 (3认同)
  • 如果我们对let做同样的事情怎么办? (2认同)
  • @GovindRai `var a, b, c; a = b = c = 10;` 与 `var a = b = c = 10;` 非常不同。所以,接受的答案是正确的。您正在解决与接受的答案无关的问题。 (2认同)

Dou*_*urn 8

当尝试将多个变量初始化为相同的值时,还有另一个选项不会引入全局陷阱。从长远来看是否可取是一个判断电话。它可能会更慢,可能会或可能不会更具可读性。在您的特定情况下,我认为长距离可能更易读,更易维护且速度更快。

其他方式使用解构赋值

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, '  '));
Run Code Online (Sandbox Code Playgroud)

这使您可以初始化一组varletconst在一行中的变量相同的值都具有相同的预期范围。

参考文献:

  • “编写惯用的 JavaScript,让我们担心 JavaScript 性能的低级部分”——Benedikt Meurer,V8 性能专家。 (3认同)
  • 不过要小心。如果使用此方法将对象、函数或数组分配给多个变量,则每个变量都将是“相同”对象的别名。对一个的修改会影响其他的...... (2认同)

小智 7

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

let [moveUp, moveDown, moveLeft, moveRight, mouseDown, touchDown] = Array(6).fill(false);
Run Code Online (Sandbox Code Playgroud)