为什么这是无效的左手边? [英] Why is this an invalid assignment left hand side?
问题描述
为什么我要执行以下操作:
Why can I do the following operations:
var b1, b2;
b1 = b2 = true;
document.write(b1," ", b2);
document.write("<br>");
b1 = !b2;
document.write(b1," ", b2);
document.write("<br>");
b1 = b2 = !true;
document.write(b1," ", b2);
但是,当我尝试以下操作时,我收到了ReferenceError: invalid assignment left-hand side
吗?
Yet when I try the following operation I recieve a ReferenceError: invalid assignment left-hand side
?
var b1, b2;
b1 = !b2 = true;
document.write(b1," ", b2);
很明显,我不能这样做,但是我找不到为什么不能这样做的解释. MDN开发人员指南,用于错误状态:
It's obvious that I can't do this, but I can't find an explanation as to why I can't. The MDN developer guide for the error states:
某处发生了意外的任务.例如,这可能是由于赋值运算符和比较运算符不匹配所致.当单个"="符号为变量分配值时,"=="或"==="运算符会比较一个值.
There was an unexpected assignment somewhere. This might be due to a mismatch of a assignment operator and a comparison operator, for example. While a single "=" sign assigns a value to a variable, the "==" or "===" operators compare a value.
所有的赋值运算符都如经证明的那样单独工作,那么为什么不能将其合并为单个运算/链式赋值呢?
All of the assignment operators work individually as proven, so why can't this be combined into a singular operation / chained assignment?
推荐答案
当您尝试执行此操作时:
When you try to do this:
var b1, b2;
b1 = !b2 = true;
document.write(b1, " ", b2);
因为它们在功能上是等效的‡,您基本上是在这样做:
Because they are functionally equivalent‡ you are basically doing:
var b1, b2;
!b2 = true;
b1 = true; //just the value of b2, not b2 itself
document.write(b1, " ", b2);
在行!b2 = true
中,您试图将一个计算结果为值(左侧)的表达式分配给一个值-完全没有意义.这样想吧:
In the line !b2 = true
, you are trying to assign an expression that evaluates to a value (the left side) to a value - that makes absolutely no sense. Think about it this way:
-
!b2
被分配给true
.!b2
是一个表达式,并且被评估为布尔值 value ,而不是变量. - 这类似于执行
1 + 1 = 2
.由于1 + 1
的值是 ,因此您不能将其分配给另一个值2
.您必须为变量分配一个值,因为按值分配在语义和逻辑上都是无效的. - 考虑上述问题的另一种方法是实现这一点:
1 + 1
是一个值.2
是一个值.您无法将值分配给值,因为该值已具有值.诸如2
的常量的值为2
,无法更改.如果我们尝试1 - 1 = 2
怎么办?0
,一个常量和值,不能为2
,因为它是一个常量.
!b2
is being assigned totrue
.!b2
is an expression and is evaluated to a boolean value, not variable.- This would be analogous to doing
1 + 1 = 2
. Since1 + 1
is evaluated to a value, you can't assign that to2
, another value. You must assign a value to variable, as value-to-value assignment is semantically and logically invalid. - Another way to think about the above is to realize this:
1 + 1
is a value.2
is a value. You cannot assign a value to a value, as that value already has a value. A constant such as2
has value2
, it cannot be changed. What if we tried1 - 1 = 2
?0
, a constant and value, cannot be2
, because it is a constant.
因此,将值分配给值在语义和逻辑上都是无效的.您不能像将false
分配给true
一样将0
分配给2
.
Thus, it is semantically and logically invalid to assign a value to a value. You cannot assign 0
to 2
just as you can't assign false
to true
.
如果您想更好地理解语法和语义,以及为什么要抛出ReferenceError
,则可以深入研究
If you want to understand the syntax and semantics better, and why this throws a ReferenceError
, you can delve into the ECMAScript® 2015 Language Specification†. Per the specification:
第12.14.1节 -赋值运算符-静态语义:早期错误
Section 12.14.1 - Assignment Operators - Static Semantics: Early Errors
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
- 这是早期的参考如果
LeftHandSideExpression
既不是ObjectLiteral
也不是ArrayLiteral
和LeftHandSideExpression
的IsValidSimpleAssignmentTarget
,则错误em>是错误的.
- It is an early Reference Error if
LeftHandSideExpression
is neither anObjectLiteral
nor anArrayLiteral
andIsValidSimpleAssignmentTarget
ofLeftHandSideExpression
is false.
IsValidSimpleAssignmentTarget
所在的位置:
第12.14节.3 -赋值运算符-静态语义:IsValidSimpleAssignmentTarget
Section 12.14.3 - Assignment Operators - Static Semantics: IsValidSimpleAssignmentTarget
AssignmentExpression :
YieldExpression
ArrowFunction
LeftHandSideExpression = AssignmentExpression
LeftHandSideExpression AssignmentOperator AssignmentExpression
1.返回false.
1. Return false.
现在回头看看您的代码:b1 = !b2 = true
. b1 = !b2
很好,因为它是 LeftHandSideExpression = AssignmentExpression
,因此对于IsValidSimpleAssignmentTarget
返回true.当我们检查!b2 = true
时会出现问题.如果我们看一下 LeftHandSideExpression
的定义:
Now look back at your code: b1 = !b2 = true
. b1 = !b2
is fine because it is LeftHandSideExpression = AssignmentExpression
, thus returning true for IsValidSimpleAssignmentTarget
. The problem arises when we check !b2 = true
. If we look at the definition of LeftHandSideExpression
:
第12.3节 -左手表情
语法
LeftHandSideExpression :
NewExpression
CallExpression
(您可以在上面的规范链接中查看 NewExpression
和 CallExpression
的定义)
(You can view the definitions of NewExpression
and CallExpression
in the specification link above)
您会看到!b2 = true
不是有效的 AssignmentExpression
,因为它不符合条件 LeftHandSideExpression = AssignmentExpression
.这是因为!b2
不是有效的 LeftHandSideExpression
,也不是 ObjectLiteral
也不是 ArrayLiteral
,因此IsValidSimpleAssignmentTarget
返回false,并抛出ReferenceError
.请注意,该错误是 早期错误,这意味着它会在执行任何代码之前抛出,如
You can see that !b2 = true
is not a valid AssignmentExpression
, as it does not fit the criteria LeftHandSideExpression = AssignmentExpression
. This is because !b2
is not a valid LeftHandSideExpression
, also not an ObjectLiteral
nor ArrayLiteral
, thus IsValidSimpleAssignmentTarget
returns false, throwing the ReferenceError
. Note that the error is an early error, meaning it is thrown before any code is executed, as noted in @Bergi's comment.
您可以通过执行以下任一操作来解决此问题,具体取决于所需的结果:
You can combat this by doing either of the following, depending on your desired outcome:
b1 = !(b2 = true);
使用括号时,括号内的优先级高于外部.这样,就分配了b2
,并且由于它是true
,因此括号内的值将为true
.接下来,它等效于:
With parentheses, inside the parentheses takes precedence over outside. That way, b2
is assigned, and since it is true
, inside the parentheses evaluates to true
. Next, it's equivalent to:
b1 = !(true);
如上所述,括号内的
As被评估为true
. b1
将与b2
相反,而b2
将是true
.
As inside the parentheses is evaluated to true
as mentioned above. b1
will be the opposite of b2
as expected, and b2
will be true
.
如果您希望b1
是true
,而b2
是false
,则重新组织语句,如下所示:
If you wanted b1
to be true
and b2
to be false
, restructure the statement like this:
b2 = !(b1 = true);
这样,它与上面的完全相反,给出了b1 = true
和b2 = false
.
This way, it's the exact opposite of the above, giving b1 = true
, and b2 = false
.
‡正如注释中提到的@Bergi一样,b1
被分配了正确的操作数,在这种情况下,true
被分配了正确的操作数,而不是!b2
.
‡As @Bergi mentioned in the comments, b1
is assigned the right operand, true
in this case, not !b2
.
†尽管大多数浏览器目前不支持ECMAScript 6(2015)的所有功能,而是使用
†Although most browsers currently do not support all features of ECMAScript 6 (2015), and instead use ECMAScript 5.1 (2011), the specification is the same for both versions. All definitions are the same, and thus the explanation is still valid.
这篇关于为什么这是无效的左手边?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!