2010-06-03 89 views
13

我看到这个结构是为了得到浏览器的视口宽度:为什么Javascript的OR返回的值不是true/false?

function() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; } 

我理解所涉及的浏览器怪癖。我不明白的是为什么||返回值。所以我尝试了这个alert(undefined || 0 || 3);,果然,它会警告3。我觉得这很离奇,因为我期待truefalse。谁能解释一下发生了什么?

+0

是否'警报(未定义&& 0 && 3)''返回0'? – 2010-06-03 13:38:13

+2

@Rising Star:为什么问OP,你可以自己动手吗?...另外,对我而言,它返回'undefined'。 – Matchu 2010-06-03 13:39:34

+3

供参考:如果你想要一个真值,做'!!(undefined || 0 || 3)' – Matt 2010-06-03 14:03:51

回答

13

在ECMAScript的标准部分11.11 Binary Logical Operators

生产LogicalORExpression请看: LogicalORExpression || LogicalANDExpression评估为 如下:

1.评估LogicalORExpression。

2.Call GetValue(Result(1))。

3.Call ToBoolean(Result(2))。

4.如果Result(3)为true,则返回Result(2)。

5.评估逻辑和表达式。

6.Call GetValue(Result(5))。

7.返回结果(6)。

所以评估布尔转换每个操作数,但返回操作数的实际

如果你想知道如何使用Javascript的值转换为布尔值,见9.2 ToBoolean

17

JavaScript的运营商||定义为返回左值,如果计算结果是truthy值,否则正确的价值而不是返回true本身。这就是它在规范中的定义。

我知道它有时可能很烦人,你可能会不小心结束了对你不想坚持的事情的引用,但它也允许你的例子有一个方便的技巧。一切都有其优点和缺点。

4

OR函数是一个短路或评估 - 它返回第一个不是假的元素,否则返回最后一个false元素。

其实,这是非常有用的,所以你可以写像

a = a || someValue; 

这是一样的

if (a==null) 
    a = someValue; 
+1

这不仅仅是“不为空”。空字符串和数字零都被视为“false”。 “未定义”伪值也被视为“假”,尽管这是事情变得更加棘手的地方。编辑: – Pointy 2010-06-03 13:45:35

+0

:现在使用true和false作为定义。查看ECMA标准,它通过toBoolean将每个值转换为布尔值,但在测试后返回值本身。 – mdma 2010-06-03 16:11:36

9

不要把它想成“或”表达式。它更像是一个表达式中的流量控制设备。 ||的值表达式是第一个“truthy”子表达式的值。因此,该系列的子表达式的评估停止在某些时候,仿佛

expr1 || expr2 || expr3 

(function() { 
    var rv = expr1; 
    if (rv) return rv; 
    rv = expr2; 
    if (rv) return rv; 
    return expr3; 
})() 
1

某些值,例如零,""undefined,被视为假。其他的都是真的,所以||运算符只是返回它给出的对中的第一个非零(即真)值。这对于像上面的代码这样的技巧很有用,但我猜测它并没有添加到语言中,只是为了让您跳过奇怪的if语句。因为更高级别的语言(比如BASIC ...是的,也许是更高级别的一个奇怪的定义)使用固定的常量来表示true和false--通常是0和-1,或0和1.

+2

注意“任何非零”的定义。 'false','undefined'和'“”'都不为零,但不认为是真的。 – Matchu 2010-06-03 13:43:26

+0

@Matchu谢谢,这是我的perl背景显示。 :(固定的 – 2010-06-03 14:08:39

+0

我喜欢把||和&&的行为看作“确定真实性或虚假性的论证的价值”。 – 2013-08-17 20:33:55

2

这只是它的设计方式。 ||,就像&&是一个短路操作符,按顺序评估表达式,在表达式满足条件并产生表达式结果后停止。同样是真实的&&

var myObj = { "Test": { "Foo":"Bar" } }; 
var myObj2 = { "Foo": "Bar" }; 

alert(myObj.Test && myObj.Test.Foo); // will alert "Bar"; 
alert(myObj2.Test && myObj2.Test.Foo); // will alert undefined; 
相关问题