使用JavaScript进行多个左侧分配


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

这等效于:

var var1 = var2 = var3 = 1;

我相当确定这是定义变量的顺序:var3,var2,var1,这等效于此:

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

有什么方法可以用JavaScript确认吗?可能使用一些分析器?



如果我使用,这也适用this.var1 = this.var2 = this.var3 = 1吗?
Gangadhar JANNU

Answers:


404

其实,

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));

44
堂,那是出乎意料的 感谢您的提示,我会注意的。
David Calhoun,2009年

10
@ SkinnyG33k,因为它是从右到左。因此它将在最左边之前解析最右边。这样var var1=var2发生在var3 = 1前后var2 = var3。就像var3=1; var2=var3; var var1=var2
gcb

12
请注意:如果您知道要提前进行此类操作,则仍然可以从任务中分解定义。因此:var v1, v2, v3;然后,以后:v1 = v2 = v3 = 6;它们仍将在本地范围内。由于David提到了警报,因此可以按预期工作(如果进行了预可变):alert(v1 = v2 = v3 = 6);
ShawnFumo

3
究竟。但是,如果我们遵循一些常见的最佳实践,在这种情况下,可以通过在顶部声明变量来避免不必要的错误,并避免局部变量泄漏到全局范围内。请参阅:jsfiddle.net/gleezer/r9Mu8/1
大雄

1
“党,这是出乎意料的。” 为什么这会出乎意料?大多数语言都要求您在使用前声明变量。JavaScript也不例外,如果您忽略声明变量,则默认为全局窗口对象。开始在JavaScript中使用“ use strict”,您将成为一个更好的JavaScript程序员。
cchamberlain 2015年

19

JavaScript中的分配从右到左起作用。var var1 = var2 = var3 = 1;

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

您可以认为它等同于 var var1 = (var2 = (var3 = 1));首先评估最里面的括号的位置。


1
谢谢,这绝对有帮助。如果从右到左进行评估,则有助于思考将引发什么错误(在这种情况下,错误是var1 / var2未定义)。
David Calhoun,2009年

5
这实际上是语法错误。您不能在此(之后立即拥有var。删除括号的外部集可以使其编译无误var var1 = (var2 = (var3 = 1));。当时我觉得它并没有很好地说明这一点,但我想它也是一样。
贾斯汀·约翰逊(

var var1 = var2 = var3 = 1;. 等于 var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms

8

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

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

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

这不等于:

var var1 = var2 = var3 = 1;

在这种情况下,screens 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; 

8
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运算符优先级(操作顺序)

请注意,逗号运算符实际上是特权最低的运算符,而括号是特权最高的运算符,并且在构造单行表达式时它们会齐头并进。


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

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

windowInnerHeight(); // a thunk

4

试试这个:

var var1=42;
var var2;

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

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

从逻辑上讲,分配必须从右到左链接在一起。但是,由于这对javascript来说是原子的(没有线程),因此特定引擎可能会选择实际进行一些优化。


1
感谢你的回答。我想我一直在寻找一种使用警报的方式,同时仍然保持多重分配结构(a = b = c),但我认为这是不可能的。
David Calhoun,2009年

1
像javascript中那样的单个语句(尽管有多个表达式,但全部都可以处理为单个语句),可以视为原子语句。您必须将其分解。
Joel Coehoorn

1

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

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

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.