【问题标题】:Multiple left-hand assignment with JavaScript使用 JavaScript 进行多个左手赋值
【发布时间】:2010-12-18 00:45:45
【问题描述】:
var var1 = 1,
    var2 = 1,
    var3 = 1;

这等价于:

var var1 = var2 = var3 = 1;

我很确定这是定义变量的顺序:var3、var2、var1,这相当于:

var var3 = 1, var2 = var3, var1 = var2;

有没有办法在 JavaScript 中确认这一点?可能使用一些分析器?

【问题讨论】:

  • 分配发生在右侧 javascript operator precedence
  • 如果我使用this.var1 = this.var2 = this.var3 = 1,这是否也适用?
  • 是的,直到它是全局变量,因为this 指的是窗口对象。

标签: javascript variables variable-assignment


【解决方案1】:

试试这个:

var var1=42;
var var2;

alert(var2 = var1); //show result of assignment expression is assigned value
alert(var2); // show assignment did occur.

请注意第一个警报中的单个“=”。这将显示赋值表达式的结果是赋值,第二个警报将显示赋值确实发生了。

从逻辑上讲,赋值必须从右到左链接。但是,由于这对 javascript 来说都是原子性的(没有线程),因此特定引擎可能会选择以不同方式对其进行实际优化。

【讨论】:

  • 感谢您的回答。我想我正在寻找一种在使用警报的同时仍保持多重分配结构 (a=b=c) 的方法,但我认为这是不可能的。
  • 像 javascript 中的单个语句(并且,虽然有几个表达式,但都适用于单个语句)可以被认为是原子的。你必须打破它。
【解决方案2】:

javascript 中的赋值从右到左工作。 var var1 = var2 = var3 = 1;

如果这些变量中的任何一个的值在此语句之后是1,那么从逻辑上讲它必须从右边开始,否则值或var1var2将是未定义的。

你可以认为它等同于var var1 = (var2 = (var3 = 1));,其中最里面的括号集首先被计算。

【讨论】:

  • 谢谢,这绝对有帮助。考虑一下如果不是从右到左计算会引发哪些错误(在这种情况下,错误将是 var1/var2 未定义)。
  • 其实是语法错误。您不能在var 之后立即拥有(。删除外部括号集允许它无错误地编译,var var1 = (var2 = (var3 = 1));。当时我觉得它并没有很好地说明这一点,但我想它是一样的。
  • var var1 = var2 = var3 = 1;. 等于 var var3 = 1; var var2 = var3; var var1 = var2;
【解决方案3】:

其实

var var1 = 1, var2 = 1, var3 = 1;

等价于:

var var1 = var2 = var3 = 1;

区别在于范围:

function good() {
  var var1 = 1, var2 = 1, var3 = 1;
}

function bad() {
  var var1 = var2 = var3 = 1;
}

good();
console.log(window.var2); // undefined

bad();
console.log(window.var2); // 1. Aggh!

实际上这表明赋值是右结合的。 bad 示例等价于:

var var1 = (window.var2 = (window.var3 = 1));

【讨论】:

  • 当,这出乎意料。感谢您的提示,我会注意的。
  • 我不明白...为什么 bad() 中的变量会超出函数范围?函数完成后它们不应该被垃圾收集吗?
  • @SkinnyG33k 因为它是从右到左的。所以它会在最左边解析最右边。所以var var1=var2 发生在var3 = 1var2 = var3 之后。就像var3=1; var2=var3; var var1=var2
  • 请注意:如果您知道要提前做这种事情,您仍然可以从作业中拆分定义。所以:var v1, v2, v3; 稍后:v1 = v2 = v3 = 6; 他们仍将在本地范围内。由于大卫提到警报,这将按预期工作(如果 pre-var'd):alert(v1 = v2 = v3 = 6);
  • 没错。但是如果我们遵循一些常见的最佳实践,在这种情况下,通过在顶部声明我们的变量,我们可以避免不必要的错误并避免局部变量泄漏到全局范围。见:jsfiddle.net/gleezer/r9Mu8/1
【解决方案4】:
a = (b = 'string is truthy'); // b gets string; a gets b, which is a primitive (copy)
a = (b = { c: 'yes' }); // they point to the same object; a === b (not a copy)

(a && b) 在逻辑上是 (a ? b : a),其行为类似于乘法(例如,!!a * !!b

(a || b) 逻辑上是(a ? a : b) 并且表现得像加法(例如!!a + !!b

(a = 0, b)是不关心a是否真实的缩写,隐式返回b


a = (b = 0) && "nope, but a is 0 and b is 0"; // b is falsey + order of operations
a = (b = "b is this string") && "a gets this string"; // b is truthy + order of ops

JavaScript Operator Precedence (Order of Operations)

请注意,逗号运算符实际上是特权最低的运算符,但括号是特权最高的,它们在构造单行表达式时是相辅相成的。


最终,您可能需要“thunk”而不是硬编码值,对我来说,thunk 既是函数又是结果值(相同的“事物”)。

const windowInnerHeight = () => 0.8 * window.innerHeight; // a thunk

windowInnerHeight(); // a thunk

【讨论】:

    【解决方案5】:

    coffee-script 可以从容地做到这一点..

    for x in [ 'a', 'b', 'c' ] then "#{x}" : true
    

    [ { a: true }, { b: true }, { c: true } ]

    【讨论】:

    • 这并不能真正回答问题。请重新阅读问题。
    • 谁在乎coffeescript
    【解决方案6】:

    var var1 = 1, var2 = 1, var3 = 1;

    在这种情况下,var 关键字适用于所有三个变量。

    var var1 = 1,
        var2 = 1,
        var3 = 1;
    

    这不等同于:

    var var1 = var2 = var3 = 1;

    在这种情况下,屏幕后面的var关键字仅适用于var1,因为变量提升和表达式的其余部分被正常评估,因此变量var2, var3正在成为全局变量

    Javascript 按此顺序处理此代码:

    /*
    var 1 is local to the particular scope because of var keyword
    var2 and var3 will become globals because they've used without var keyword
    */
    
    var var1;   //only variable declarations will be hoisted.
    
    var1= var2= var3 = 1; 
    

    【讨论】:

      【解决方案7】:

      现在很明显,它们并不相同。编码方式是

      var var1, var2, var3
      var1 = var2 = var3 = 1
      

      那么,让分配呢?和 var 完全一样,不要让 let 赋值因为块作用域而迷惑你。

      let var1 = var2 = 1 // here var2 belong to the global scope
      

      我们可以这样做:

      let v1, v2, v3
      v1 = v2 = v3 = 2
      

      注意:顺便说一句,我不建议使用多个赋值,甚至不建议在同一行中使用多个声明。

      【讨论】:

        猜你喜欢
        • 2015-03-07
        • 2013-04-27
        • 2016-11-16
        • 2015-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-26
        • 2013-10-25
        相关资源
        最近更新 更多