逻辑和或运算符是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中的逻辑运算符是正确关联的:
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发布于 2013-12-17 18:54:21
对于任何优秀的编译器,这些操作符的选择相关性几乎都是无关的,并且输出的代码将是相同的。是的,解析树是不同的,但是发出的代码不需要。
在我所知道的C族的所有语言中( Javascript也属于这些语言),逻辑运算符都是相联的。所以真正的问题是,为什么类C语言将逻辑运算符定义为左联想呢?由于所选择的结合性是不相关的(就语义和效率而言),我怀疑最“自然的”(如“大多数其他运算符所使用的东西”)是选择了结合性,尽管我没有任何来源来支持我的说法。其他可能的解释是,左关联运算符使用LALR解析器解析时占用较少的堆栈空间(这现在不是什么大问题,但可能在C出现时就回来了)。
发布于 2013-12-24 04:04:04
考虑以下代码:
console.log( true || (false && true) ); // right associative (implicit)
console.log( (true || false) && true ); // left associative (Javascript)这两个例子实际上都返回相同的结果,但这并不是担心运算符结合性的原因。之所以与此相关,是因为逻辑运算符决定其结果的独特方式。即使所有排列最终得出相同的最终结论,计算的顺序也会发生变化,这可能对代码有很大的影响。
所以,现在考虑一下::
var name = "";
// ----------------------------------------
// Right associative
// ----------------------------------------
name = "albert einstein";
console.log("RIGHT : %s : %s", true || (false && updateName()), name);
// ----------------------------------------
// Left Associative
// ----------------------------------------
name = "albert einstein";
console.log("LEFT : %s : %s", (true || false) && updateName(), name);
function updateName() {
name = "charles manson";
return true;
}输出是:
RIGHT : true : albert einstein
LEFT : true : charles manson这两个表达式都返回true,但只有与左关联的版本才需要调用updateName()才能返回答案。正确的关联版本不同。它只计算(false && updateName())中的第一个参数,因为第二个参数不能将false更改为true。
记住这两点:
请注意,上述两点都不改变单个表达式的解释方式,只改变复合表达式的解释方式。结合性发生在更高的层次上。
运算符结合性以及运算符优先性对语言的行为有着巨大的影响。理解这些差异对于能够使用和快速掌握不同编程语言中的功能差异至关重要。对于你的问题,你一定会得到我的赞许,我希望这能澄清一些问题。保重。
发布于 2013-12-23 22:54:00
简单的答案是:假设var i= null;if (i == null \x\x i.getSomeValue()) .当没有关联时,将首先评估第二个测试,从而给出一个异常。
https://stackoverflow.com/questions/20591876
复制相似问题