omiga

简单就好

逻辑AND(&&)运算符

发表评论»

先看下面这段代码,注释有运行结果。

var t = true;
var f = false;
var i = 1;
var s = "hello";
var a = [1,10,100];
alert("t&&i: " + (t && i)); //1
alert("f&&i: " + (f && i)); //false

alert("i&&t: " + (i && t)); //true
alert("i&&f: " + (i && f)); //false

alert("i&&s: " + (i && s)); //"hello"
alert("i&&a: " + (i && a)); //1,10,100

alert("s&&i: " + (s && i)); //1
alert("a&&i: " + (a && i)); //1

再看来自w3school的一段文字:

如果某个运算数不是原始的 Boolean 型值,逻辑 AND 运算并不一定返回 Boolean 值:

  • 如果一个运算数是对象,另一个是 Boolean 值,返回该对象。
  • 如果两个运算数都是对象,返回第二个对象。
  • 如果某个运算数是 null,返回 null。
  • 如果某个运算数是 NaN,返回 NaN。
  • 如果某个运算数是 undefined,发生错误。

第一条:如果一个运算数是对象,另一个是 Boolean 值,返回该对象。如果这种说法成立,那么先前测试中的以下代码都应输出i。

alert("t&&i: " + (t && i)); //1
alert("f&&i: " + (f && i)); //false

alert("i&&t: " + (i && t)); //true
alert("i&&f: " + (i && f)); //false

但实际并非如此。再看规则第二条:如果两个运算数都是对象,返回第二个对象。对先前的测试代码稍作修改,把0赋值给i:

var t = true;
var f = false;
var i = 0;
var s = "hello";
var a = [1,10,100];
alert("t&&i: " + (t && i)); //0
alert("f&&i: " + (f && i)); //false

alert("i&&t: " + (i && t)); //0
alert("i&&f: " + (i && f)); //0

alert("i&&s: " + (i && s)); //0
alert("i&&a: " + (i && a)); //0

alert("s&&i: " + (s && i)); //0
alert("a&&i: " + (a && i)); //0

i与另外一个不是boolean类型的运算数的AND运算都返回了i,并不是规则中所说的第二个对象。

再看如下代码,将字符串s赋值成空字符串,将数组a也赋值为空数组:

var i = 0;
var s = "";
var a = [];

alert("i&&s: " + (i && s)); //0
alert("i&&a: " + (i && a)); //0

alert("s&&i: " + (s && i)); //""
alert("a&&i: " + (a && i)); //0

于是,我的结论是:AND(&&) 运算不论运算数的类型是什么,如果运算结果为true,那么返回第二个运算数;如果运算结果为false,那么返回第一个布尔值等于(==)false的运算数。似乎这个结论是正确的,但是仔细看看最后一条测试语句的结果,并不遵循所得出的结论。

其实这里又涉及到另外一个typeof为object的值的布尔运算问题,如果object类型的值为空那么等于运算符(==)会视其为false,但是其他运算符则会视其为true。所以也才有了下面的现象:

alert([]==false); //true
if([]) alert("ok"); //ok

所以AND(&&)运算符测试中的最后一句a&&i其结果为false,但是a为true,所以有结果0。

如此看来,我们得出的结论也是完全正确的。