2. 位运算NOT
位运算NOT由否定号(~)表示,它是ECMAScript中为数不多的与二进制算术有关的运算符之一。位运算NOT是三步的处理过程:
(1) 把运算数转换成32位数字;
(2) 把二进制形式转换成它的二进制反码;
(3) 把二进制反码转换成浮点数。
例如:
![]()
位运算NOT实质上是对数字求负,然后减1,因此25变为-26。用下面的方法也可以得到同样的效果:
![]()
3. 位运算AND
位运算AND由和号(&)表示,直接对数字的二进制形式进行运算。它把每个数字中的数位对齐,然后用下面的规则对同一位置上的两个数位进行AND运算:
|
第一个数字中的数位 |
第二个数字中的数位 |
结 果 |
|
1 |
1 |
1 |
|
1 |
0 |
0 |
|
0 |
1 |
0 |
|
0 |
0 |
0 |
例如,要对数字25和3进行AND运算,代码如下所示:
![]()
25和3进行AND运算的结果是1。为什么?分析如下:
![]()
可以看到,在25和3中,只有一个数位(位0)存放的都是1,因此,其他数位生成的都是0,所以结果为1。
4. 位运算OR
位运算OR由符号(|)表示,也是直接对数字的二进制形式进行运算。在计算每个位时,OR采用下列规则:
|
第一个数字中的数位 |
第二个数字中的数位 |
结 果 |
|
1 |
1 |
1 |
|
1 |
0 |
1 |
|
0 |
1 |
1 |
|
0 |
0 |
0 |
仍然使用AND运算所用的例子,对25和3进行OR运算,代码如下:
![]()
25和3进行OR运算的结果是27:
![]()
可以看到,在两个数字中,共有4个数位存放的是1,这些数位被传递给结果。二进制代码11011等于27。
5. 位运算XOR
位运算XOR由符号(^)表示,当然,也是直接对二进制形式进行运算。XOR不同于OR,当只有一个数位存放的是1时,它才返回1。真值表如下:
|
第一个数字中的数位 |
第二个数字中的数位 |
结 果 |
|
1 |
1 |
0 |
|
1 |
0 |
1 |
|
0 |
1 |
1 |
|
0 |
0 |
0 |
对25和3进行XOR运算,代码如下:
![]()
25和3进行XOR运算的结果是26:
![]()
可以看到,两个数字中共有4个数位存放的是1,它们被传递给结果。二进制代码11010等于26。
6. 左移运算
左移运算由两个小于号表示(<<)。它把数字中的所有数位向左移动指定的数量。例如,把数字2(等于二进制中的10)左移5位,结果为64(等于二进制中的1000000):
![]()
注意,在左移数位时,数字右边多出5个空位。左移运算用0填充这些空位,使结果为完整的32位数字(如图2-6所示)。
注意,左移操作保留数字的符号位。例如,如果把-2左移5位,得到的是-64,而不是64。“符号仍然存储在第32位中吗?”是的,不过这在ECMAScript后台进行,开发者不能直接访问第32个数位。即使输出二进制字符串形式的负数,显示的也是负号形式(例如,-2将显示为-10,而不是11111111111111111111111111111110)。

7. 有符号右移运算
有符号右移运算符由两个大于号(>>)表示,它将把32位数字中的所有数位整体右移,同时保留该数的符号(正号或负号)。有符号右移运算恰好与左移运算相反。例如,把64右移5位,将变为2:
![]()
同样,移动数位后会造成空位。这次,空位位于数字的左侧,但位于符号位之后(如图2-7所示)。ECMAScript用符号位的值填充这些空位,创建完整的数字。
8. 无符号右移运算
无符号右移由三个大于号(>>>)表示,它将把无符号32位数中的所有数位整体右移。对于正数,无符号右移运算的结果与有符号右移运算一样。用有符号右移运算中的例子,把64右移5位,将变为2:
![]()
对于负数,情况就不同了。无符号右移运算用0填充所有空位。对于正数,这与有符号右移运算的操作完全一样,而负数则被作为正数来处理。由于无符号右移运算的结果是一个32位的正数,所以负数的无符号右移运算得到的总是一个非常大的数字。例如,如果把-64右移5位,将得到134217726。如果得到这种结果的呢?
要实现这一点,需要把这个数字转换成无符号的等价形式(尽管该数字本身还是有符号的),可以通过以下代码获得这种形式:
var iUnsigned64 = -64 >>> 0;
然后,用Number类型的toString()方法获取它的真正的位表示,采用的基为2:
alert(iUnsignedNeg64.toString(2));
这将生成11111111111111111111111111000000,即有符号整数-64的二进制补码表示,不过它等于无符号整数4294967232。出于这种原因,使用无符号右移运算符要小心。
2.9.3 Boolean运算符
Boolean运算符与等式运算符同等重要,是它们使得程序设计语言得以正常运行。如果不能测试两个值之间的关系,那么像if...else和循环这样的语句就没用了。Boolean运算符有三种,即NOT、AND和OR。
1. 逻辑NOT
在ECMAScript中,逻辑NOT运算符与C和Java中的逻辑NOT运算符相同,都由感叹号(!)表示。与逻辑OR和逻辑AND运算符不同的是,逻辑NOT运算符返回的一定是Boolean值。逻辑NOT运算符的行为如下:
q 如果运算数是对象,返回false。
q 如果运算数是数字0,返回true。
q 如果运算数是0以外的任何数字,返回false。
q 如果运算数是null,返回true。
q 如果运算数是NaN,返回true。
q 如果运算数是undefined,发生错误。
通常,该运算符用于控制循环(后面有相关的讨论):
![]()

在这个例子中,Boolean变量(bFound)用于记录检索是否成功。找到问题中的数据项时,bFound将被设置为true,!bFound将等于false,意味着运行将跳出while循环。
判断ECMAScript变量的Boolean值时,也可以使用逻辑NOT运算符。这样做需要在一行代码中使用两个逻辑NOT运算符。无论运算数是什么类型的,第一个NOT运算符返回Boolean值。第二个NOT将对该Boolean值求负,从而给出变量真正的Boolean值。

运行这个例子,生成的输出如下所示:

2. 逻辑AND运算符
在ECMAScript中,逻辑AND运算符用双和号(&&)表示:
![]()
下面的真值表描述了逻辑AND运算符的行为:
|
运算数1 |
运算数2 |
结 果 |
|
true |
true |
true |
|
true |
false |
false |
|
false |
true |
false |
|
false |
false |
false |
逻辑AND运算的运算数可以是任何类型的,不止是Boolean值。如果某个运算数不是原始的Boolean型值,逻辑AND运算并不一定返回Boolean值:
q 如果一个运算数是对象,另一个是Boolean值,返回该对象。
q 如果两个运算数都是对象,返回第二个对象。
q 如果某个运算数是null,返回null。
q 如果某个运算数是NaN,返回NaN。
q 如果某个运算数是undefined,发生错误。
与Java中的逻辑AND运算相似,ECMAScript中的逻辑AND运算也是简便运算,即如果第一个运算数决定了结果,就不再计算第二个运算数。对于逻辑AND运算来说,如果第一个运算数是false,那么无论第二个运算数的值是什么,结果都不可能等于true。考虑下面的例子:
![]()
这段代码在进行逻辑AND运算时将引发错误,因为变量bUnknown是未定义的。变量bTrue的值为true,因此逻辑AND运算将继续计算变量bUnknown。这样做就会引发错误,因为bUnknown的值是undefined,不能用于逻辑AND运算。如果修改这个例子,把第一个运算数设为false,那么就不会发生错误:
![]()
在这段代码中,脚本将输出逻辑AND运算返回的值,即字符串"false"。即使变量bUnknown的值为undefined,它也不会被计算,因为第一个运算数的值是false。在使用逻辑AND运算符时,必须记住它的这种简便计算特性。
3. 逻辑OR运算符
ECMAScript中的逻辑OR运算符与Java中的相同,都由双竖线(||)表示:
![]()
下面的真值表描述了逻辑OR运算符的行为:
|
运算数1 |
运算数2 |
结 果 |
|
true |
true |
true |
|
true |
false |
true |
|
false |
true |
true |
|
false |
false |
|
与逻辑AND运算符相似,如果某个运算数不是Boolean值,逻辑OR运算并不一定返回Boolean值:
q 如果一个运算数是对象,另一个是Boolean值,返回该对象。
q 如果两个运算数都是对象,返回第一个对象。
q 如果某个运算数是null,返回null。
q 如果某个运算数是NaN,返回NaN。
q 如果某个运算数是undefined,发生错误。
与逻辑AND运算符一样,逻辑OR运算也是简便运算。对于逻辑OR运算符来说,如果第一个运算数值为true,就不再计算第二个运算数。例如:
![]()
与前面的例子相同,变量bUnknown是未定义的。不过,由于变量bTrue的值为true,bUnknown不会被计算,因此输出的是"true"。如果把bTrue的值改为false,将发生错误:
![]()







