【问题标题】:Assign multiple variables to the same value in Javascript?在Javascript中将多个变量分配给相同的值?
【发布时间】:2013-06-03 05:51:33
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 所有读者:在您决定将最佳答案实施到您的代码中之前,请查看下面的第二个答案。和平。
  • 不要尝试这样做,因为在内存中将只有一个变量,其他变量将是该变量的副本或引用,那么如果您从一个变量中更改值,所有变量都会受到影响
  • @LucasMatos 不适用于原语。
  • 我知道这不是答案,但我会使用一个变量“方向”,而不是将变量设置为 false,我使用三元组 = 将其与 true if(moveLeft === true ),这样你根本不需要设置初始值

标签: javascript


【解决方案1】:

没有什么能阻止你做事

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

检查这个例子

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

【讨论】:

  • 您可能想要评论在按照您建议的方式分配值时行为将如何区分原始类型和引用类型。
  • 是的,如果对一个对象执行此操作,所有变量都将是该对象的别名。 IE function MyObj(){this.x=1} var a,b; a = b = new MyObj(); ++a.x 也会增加 b.x 属性。
  • 我会说如果您没有全局范围内分配左侧的所有变量,请不要使用这种方法
  • 正如@doublejosh 所说,存在您没有解决的范围界定问题。
【解决方案2】:

没有什么能阻止您执行上述操作,但请坚持住!

有一些陷阱。 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;

长话短说,两种方法都可以正常工作,但第一种方法可能会在您的代码中引入一些有害的错误。如果不是绝对必要,不要犯在全局命名空间中乱扔局部变量的罪过。


旁注:正如 cmets 中所指出的(这不仅仅是在这个问题的情况下),如果所讨论的复制值不是原始值而是对象,您最好了解按值复制与复制引用。每当分配对象时,都会复制对对象的引用而不是实际对象。所有变量仍将指向同一个对象,因此一个变量的任何更改都将反映在其他变量中,如果您的意图是复制对象值而不是引用,那么您会非常头疼。

【讨论】:

  • 如果我们用 let 做同样的事情呢?
  • 除了 moveUp 成为块作用域之外,它没有任何区别。仍然会声明 5 个全局变量。
  • @GovindRai var a, b, c; a = b = c = 10;var a = b = c = 10; 非常不同。因此,接受的答案是正确的。您正在解决与已接受答案无关的问题。
  • @ElisByberi 感谢您的评论。你没有错。我回答的目的是解决已接受答案中的第一句话。我已经在我的回答中提供了进一步的明确性。
  • @P-RAD 只有使用 let 声明的第一个变量才会存在于封闭范围内。
【解决方案3】:

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

其他方式使用Destructuring assignment

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 变量初始化为同一行上的相同值,所有这些变量都具有相同的预期范围。

参考资料:

【讨论】:

  • 但要小心。如果使用此方法将对象、函数或数组分配给多个变量,则每个变量将是 same 对象的别名。对其中一个的修改会影响其他...
  • 创建数组赋值,请不要
  • @MartijnScheffer 为什么?如果编译代码的 JavaScript 引擎实际上创建并丢弃了一个比编译一系列直接赋值所产生的额外数组,那么它将是特定于实现且可修复的。
  • 是的,一旦代码被编译,数组仍然被创建,这使得这个方法比简单地分配值慢很多。这是不可修复的,如果你不需要,不要分配内存。只需做一个简单的测试,用两个版本的代码编写一个战利品。
  • ""编写惯用的 JavaScript,让我们担心 JavaScript 性能的低级问题"" -- Benedikt Meurer,V8 性能专家。
【解决方案4】:

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

  myArray[moveUP, moveDown, moveLeft];

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

        myArray[i] = true;

    }

【讨论】:

  • 这是非常错误的。第一个语句没有语法意义,for 循环只是为 myArray 索引分配值。
【解决方案5】:

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

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

【讨论】:

  • 不错,但分配内存只是为了做一个分配仍然是完全错误的。
  • 使用数组解构是一个不错的方法。您还可以声明一个数组并明确地将您的值放在那里,它们都相等或不同。 let [moveUp, moveDown, moveLeft, ..., touchDown] = [1, False,..., True]
猜你喜欢
  • 1970-01-01
  • 2013-04-27
  • 2019-01-27
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2014-06-04
  • 1970-01-01
相关资源
最近更新 更多