Java 具有条件运算符和赋值运算符的表达式
此Javascript表达式在所有浏览器中都能正常工作(): 现在是2点 但是为什么呢?我希望这里有一个例外,因为赋值的左侧是Java 具有条件运算符和赋值运算符的表达式,java,javascript,syntax,operator-precedence,Java,Javascript,Syntax,Operator Precedence,此Javascript表达式在所有浏览器中都能正常工作(): 现在是2点 但是为什么呢?我希望这里有一个例外,因为赋值的左侧是false?1:x,它不是有效的引用。与()比较: 这一个正在抛出一个ReferenceError。我仔细检查了,它表明条件运算符?:的优先级高于赋值运算符=,因此这两个表达式应该相同,至少我认为是这样 在Java中,类似Javascript的语法和运算符优先级规则非常相似,上面的两个表达式都会导致编译时错误,这是完全有道理的 有人能解释一下这种差异吗?正如您在MDN中发
false?1:x
,它不是有效的引用。与()比较:
这一个正在抛出一个ReferenceError
。我仔细检查了,它表明条件运算符?:
的优先级高于赋值运算符=
,因此这两个表达式应该相同,至少我认为是这样
在Java中,类似Javascript的语法和运算符优先级规则非常相似,上面的两个表达式都会导致编译时错误,这是完全有道理的
有人能解释一下这种差异吗?正如您在MDN中发现的那样,
:
比赋值运算符的前导度更高,这意味着JS将您的语句解读为:
false ? 1 : (x = 2);
乍一看,这似乎是倒退,但它的意思是:
需要三个操作数,而:
右侧的部分是第三个操作数。由于=
具有较低的优先级,x=2
成为第三个操作数
警报显示2
,因为赋值x=2
将x
变量设置为2
,然后此(子)表达式的计算结果为2
你的第二个版本:
(false ? 1 : x) = 2;
…给出一个引用错误,因为它首先执行(false?1:x)
部分,该部分的计算结果与x
相关联的值(未定义
),它不会返回变量x
本身undefined=2
不起作用。三元运算符(?)需要三个值:条件、if true和if false
在表达式中
false ? 1 : x = 2
编译器将false视为条件,1视为if true,x=2。自从优先于=尚未计算x=2。因为false本质上是false,所以x=2是返回的
当计算x=2时,返回2
这就是为什么你可以写作
x = y = 2
在本例中,x和y都设置为2
整个x=2被视为if-false操作数而不仅仅是x的原因是因为三元运算符将所有内容都带到:的右侧,如果它在范围内,则视为if-false
然而,当您使用括号时,您试图做的是将文本(无论x是什么)设置为2,从而导致错误
我无法回答为什么在javascript中它可以工作,而在java中却会导致错误的问题。我只能假设操作员优先级略有不同 以下是理解JavaScript条件表达式和Java条件表达式之间差异的两个关键点:
1
请阅读ECMAScript 5注释规范本节底部的注释:
现在,请阅读Java规范部分中的条件表达式:
1
您将注意到,正如ECMAScript 5注释所述,Java中三元运算符中的第三个操作数不能只是任何旧表达式—它只能是一个条件表达式。但是,对于ECMAScript 5,第三个操作数可以是任何AssignmentExpression
进一步查看Java规范,我们发现表达式是任何赋值表达式:
1
但是ConditionalExpression要么是带有三元运算符(…?…:…)的ConditionalExpression,要么只是一个ConditionalRexpression(在ES5中称为LogicalRexpression)(有关该信息,请参见上面的前两个链接之一)。ConditionalOrExpression的“链”可以从Java中的此处开始:
在ECMAScript 5中:
在ECMAScript 5规范中,从ConditionalExpression到基本上每一个其他表达式,在表达式类型的“链”的后面(因为它比Java规范更容易遵循),但赋值表达式最终在一开始就到达了我们的位置-主表达式:
1
上面两个代码段中的第二个操作数都是主表达式:
1
所有这些繁琐的操作(如果我没有记错的话)的结果是,在Java中,三元运算符的第三个操作数不能是赋值,但在JavaScript中可以。这就是为什么两个示例在Java中都失败了,但在JavaScript中只有第二个失败
为什么第一个可以在JavaScript中工作,而第二个不能
operand1 ? operand2 : operand3;
其工作原理与以下代码类似(实际上并非如此,但下面的代码说明了上述代码的工作原理):
因此:
变成(同样,不是实际上-下面的代码是上述代码的示例):
但是,在第二个代码段中,当使用paren时,将条件表达式与“=2;”显式分开:
变成(同样,不是实际上-下面的代码是上述代码的示例):
三元运算符的“行为类似于示例IIFE函数调用”行为将返回任何x,该x将是一个值,而不是一个无法赋值的引用。因此出现了错误。这类似于以下代码(如果x==3):
显然,我们不能这样做
我认为,在Java中,第一个运算符给出错误是因为第三个运算符不能赋值,第二个运算符给出错误是因为不能赋值(就像JavaScript中一样)
关于运算符优先级,请查看以下代码:
var x = 3;
console.log(false ? 1 : x); // ?: evaluates to "3"
console.log(false ? 1 : x = 2); // ?: evaluates to "2"
console.log(false ? 1 : x = 2, 4); // ?: evaluates to "2" - "2" and "4" arguments passed to log
console.log((false ? 1 : x = 2, 4)); // ?: evaluates to "4"
console.log((false ? 1 : x = 2), 4);
前两个在上面的IIFE说明性代码中很容易理解
第一行计算x,条件表达式计算为3,这很简单
在第二行中,我能描述它的最好方式是,条件运算符(?:)甚至会导致较低优先级的“=”运算符作为一个完整表达式进行计算,这不是因为(?:)具有较高的优先级,而是因为规范声明了以下赋值表达式:
(function () { if (false) return 1; else return x;}()) = 2;
3 = 2;
var x = 3;
console.log(false ? 1 : x); // ?: evaluates to "3"
console.log(false ? 1 : x = 2); // ?: evaluates to "2"
console.log(false ? 1 : x = 2, 4); // ?: evaluates to "2" - "2" and "4" arguments passed to log
console.log((false ? 1 : x = 2, 4)); // ?: evaluates to "4"
console.log((false ? 1 : x = 2), 4);