逻辑与和逻辑或运算符以及三元条件运算符是JavaScript中唯一的惰性运算符。它们使用以下规则进行短路求值测试:
false && anything === false
true || anything === true
这是Haskell中实现的相同方式:
(&&) :: Bool -> Bool -> Bool
False && _ = False
True && x = x
(||) :: Bool -> Bool -> Bool
True || _ = True
False || x = x
然而,根据 MDN,在 JavaScript 中逻辑运算符是左结合的。这很不直观。在我看来,它们应该是右结合的。Haskell 做得很对。Haskell 中的逻辑运算符是右结合的:
infixr 3 &&
infixr 2 ||
考虑以下Haskell表达式:
False && True && True && True
由于 Haskell 中
&&
是右结合的,因此上述表达式等同于:False && (True && (True && True))
因此,表达式
(True && (True && True))
的计算结果并不重要。由于第一个 False
,整个表达式在一步中就被简化为 False
。现在考虑如果
&&
是左结合的会发生什么。该表达式将等价于:((False && True) && True) && True
现在需要进行3次简化才能评估整个表达式:
((False && True) && True) && True
(False && True) && True
False && True
False
正如您所看到的,逻辑运算符更适合右结合。这就引出了我的实际问题:
为什么JavaScript中的逻辑运算符是左结合的?ECMAScript规范对此有何说明?JavaScript中的逻辑运算符实际上是右结合的吗?MDN文档关于逻辑运算符结合性的信息是否不正确?
编辑:根据规范,逻辑运算符是左结合的:
LogicalANDExpression = BitwiseORExpression
| LogicalANDExpression && BitwiseORExpression
LogicalORExpression = LogicalANDExpression
| LogicalORExpression || LogicalANDExpression
a && b
等同于b && a
。大多数可交换运算符也是关联的,但我发现了这个链接:http://unspecified.wordpress.com/2008/12/28/commutative-but-not-associative/。 - Barmar