零基础学JavaScript
上QQ阅读APP看书,第一时间看更新

3.9 逐位运算符

逐位运算符是一种比较复杂的运算符,可以分为逐位逻辑运算符(bitwise logical operator)与逐位位移运算符(bitwise shift operator)两种。无论是哪种逐位运算符,都必须先将操作数(要求是整型的操作数)转换成32位的二进制数值,然后再进行运算,运算完毕之后,再将结果转换成十进制数值。

3.9.1 逐位与运算符

逐位与运算符(&)是一个二元运算符,该运算符可以对左右两个操作数逐位执行AND操作,即只有两个操作数中相对应的位都为1时,该结果中的这一位才为1,否则为0。

【实例3.24】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>逐位与运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 9 & 12;
07               document.write(""9 & 12"的结果为:" + x + "<br>");
08               var y = 1 & 15;
09               document.write(""1 & 15"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行使用了&运算符。在进行逐位与操作时,逐位与运算符会先将十进制的操作数转换为二进制,再对二进制中的每一位数值逐位进行AND操作,得出结果后,再将结果转换为十进制。其操作方式如下:


十进制                       二进制
9           0000 0000 0000 0000 0000 0000 0000 1001
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 逐位与操作
8           0000 0000 0000 0000 0000 0000 0000 1000


十进制                       二进制
1           0000 0000 0000 0000 0000 0000 0000 0001
15          0000 0000 0000 0000 0000 0000 0000 1111
--------------------------------------------------- 逐位与操作
1           0000 0000 0000 0000 0000 0000 0000 0001

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample24.htm”里的内容,其运行结果如图3.12所示。

图3.12 sample24.htm的运行结果

3.9.2 逐位或运算符

逐位或运算符(|)和逐位与运算符类似,可以对左右两个操作数逐位执行OR操作。两个操作数中相对应的位只要有一个为1时,该结果中的这一位就为1,其他情况都为0。

【实例3.25】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>逐位或运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 9 | 12;
07               document.write(""9 | 12"的结果为:" + x + "<br>");
08               var y = 1 | 15;
09               document.write(""1 | 15"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行使用了“|”运算符。在进行逐位或操作时,逐位或运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位进行OR操作,得出结果后,再将结果转换为十进制。其操作方式如下:


十进制                       二进制
9           0000 0000 0000 0000 0000 0000 0000 1001
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 逐位或操作
13          0000 0000 0000 0000 0000 0000 0000 1101


十进制                       二进制
1           0000 0000 0000 0000 0000 0000 0000 0001
15          0000 0000 0000 0000 0000 0000 0000 1111
--------------------------------------------------- 逐位或操作
15          0000 0000 0000 0000 0000 0000 0000 1111

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample25.htm”里的内容,其运行结果如图3.13所示。

图3.13 sample25.htm的运行结果

3.9.3 逐位异或运算符

逐位异或运算符(^)和逐位与运算符类似,可以对左右两个操作数逐位执行异或操作。所谓异或操作是指,第1个操作数与第2个操作数相对应的位上两个数值相同时结果为0,否则为1。

【实例3.26】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>逐位异或运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 9 ^ 12;
07               document.write(""9 ^ 12"的结果为:" + x + "<br>");
08               var y = 1 ^ 15;
09               document.write(""1 ^ 15"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行使用了^运算符。在进行逐位异或操作时,逐位异或运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位进行异或操作,得出结果后,再将结果转换为十进制。其操作方式如下:


十进制                       二进制
9           0000 0000 0000 0000 0000 0000 0000 1001
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 逐位异或操作
5           0000 0000 0000 0000 0000 0000 0000 0101


十进制                       二进制
1           0000 0000 0000 0000 0000 0000 0000 0001
15          0000 0000 0000 0000 0000 0000 0000 1111
--------------------------------------------------- 逐位异或操作
14          0000 0000 0000 0000 0000 0000 0000 1110

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample26.htm”里的内容,其运行结果如图3.14所示。

图3.14 sample26.htm的运行结果

3.9.4 逐位非运算符

逐位非运算符(~)是一个一元操作符,作用于操作数之前,可以对操作数中所有位的数值取反。在JavaScript中,对一个带符号的整数进行逐位非运算,相当于将该整数改变符号后再减1。

【实例3.27】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>逐位非运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = ~12;
07               document.write(""~12"的结果为:" + x + "<br>");
08               var y = ~-15;
09               document.write(""~-15"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行使用了“~”运算符。在进行逐位非操作时,逐位非运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位取反,得出结果后再转换为十进制。其操作方式如下:


十进制                       二进制
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 逐位非操作
          1111 1111 1111 1111 1111 1111 1111 0011 (补码,最高位为1,所以是负数)
          1111 1111 1111 1111 1111 1111 1111 0010 (反码)
          0000 0000 0000 0000 0000 0000 0000 1101 (绝对值的原码,即13)


十进制                       二进制
-15        0000 0000 0000 0000 0000 0000 0000 1111 (绝对值的原码)
         1111 1111 1111 1111 1111 1111 1111 0000 (反码)
         1111 1111 1111 1111 1111 1111 1111 0001 (补码)
-------------------------------------------------- 逐位非操作
 14        0000 0000 0000 0000 0000 0000 0000 1110 (补码,最高位为0,所以是正数)

要理解以上的转换过程,必须要掌握二进制的原码、反码和补码这几个概念。

■原码:原码可以分为两个部分,第一部分为二进制的最高位,用于区分正数和负数。如果一个二进制数的最高位为0,则代表正数,如果为1则代表负数。第二部分为数值部分,用二进制的绝对值表示。例如以下代码中,第1行是+0,第2行是-0,第3行是12,第4行是-12。


0000 0000
1000 0000
0000 1100
1000 1100

■反码:对于正数而言,反码等于原码;对于负数而言,反码等于其绝对值的原码并逐位取反。例如以下代码中,第1行是12,第2行是-12。


0000 1100
1111 0011

■补码:对于正数而言,补码等于原码;对于负数而言,补码等于反码加1。例如以下代码中,第1行是12,第2行是-12。


0000 1100
1111 0100

在计算机中,所有二进制都是以补码的形式存放的。

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample27.htm”里的内容,其运行结果如图3.15所示。

图3.15 sample27.htm的运行结果

3.9.5 左移运算符

左移运算符(<<)是一个二元操作符,可以将第1个操作数中的所有数值(一共32位)向左移动,移动的位数由第2个操作数决定,因此第2个操作数应该是0~31的整数。

【实例3.28】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>左移运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 12 << 1;
07               document.write(""12 << 1"的结果为:" + x + "<br>");
08               var y = 15 << 13;
09               document.write(""15 << 13"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行执行了“<<”运算,在进行左移操作时,左移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定左移的位数。如果第2个操作数为1,则第1个操作数所有位数都向左移1位,即第1位变成第2位,第2位变成第3位,以此类推,而第32位则用0来补充。其操作方式如下:


十进制                       二进制
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 左移操作
24          0000 0000 0000 0000 0000 0000 0001 1000


十进制                       二进制
15          0000 0000 0000 0000 0000 0000 0000 1111
--------------------------------------------------- 左移操作
122880      0000 0000 0000 0001 1110 0000 0000 0000

提示

将一个值左移1位,相当于将该数值乘以2;左移2位,相当于将该数值乘以4,以此类推。

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample28.htm”里的内容,其运行结果如图3.16所示。

图3.16 sample28.htm的运行结果

3.9.6 带符号的右移运算符

带符号的右移运算符(>>)是一个二元操作符,可以将第1个操作数中的所有数值(一共32位)向右移动,移动的位数由第2个操作数决定,因此第2个操作数应该是范围在0~31的整数。

【实例3.29】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>带符号的右移运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 12 >> 1;
07               document.write(""12 >> 1"的结果为:" + x + "<br>");
08               var y = -12 >> 1;
09               document.write(""-12 >> 1"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行执行了“>>”运算,在进行带符号的右移操作时,带符号的右移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定右移的位数。如果第1个操作数为1,则第1个操作数所有位数都向右移1位,即第32位变成第31位,第31位变成第30位,以此类推。而第1位的数值补充要由原操作数的符号来决定,如果原操作数是正数,则用0来补充;如果原操作数是负数,则用1来补充。其操作方式如下:


十进制                       二进制
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 带符号的右移操作
6           0000 0000 0000 0000 0000 0000 0000 0110


十进制                       二进制
-12         1111 1111 1111 1111 1111 1111 1111 0100(补码)
--------------------------------------------------- 带符号的右移操作
-6          1111 1111 1111 1111 1111 1111 1111 1010(补码)

提示

将一个值带符号右移1位,相当于将该数值除以2(舍丢余数);右移2位,相当于将该数值除以4(舍丢余数),以此类推。

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample29.htm”里的内容,其运行结果如图3.17所示。

图3.17 sample29.htm的运行结果

3.9.7 用0补足的右移运算符

用0补足的右移运算符(>>>)与带符号的左移运算符类似,只是在右移时,最左侧的数值都是用0来补充的。

【实例3.30】请看以下代码,注意加粗的文字。


01   <html>
02      <head>
03         <title>用0补足的右移运算符</title>
04         <script type="text/javascript">
05            <!--
06               var x = 12 >>> 1;
07               document.write(""12 >>> 1"的结果为:" + x + "<br>");
08               var y = -12 >>> 1;
09               document.write(""-12 >>> 1"的结果为:" + y + "<br>");
10            -->
11         </script>
12      </head>
13      <body>
14      </body>
15   </html>

【代码说明】代码第6行和第8行执行了“>>>”运算,在进行用0补足的右移操作时,用0补足的右移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定右移的位数。如果第2个操作数为1,则第1个操作数所有位数都向右移1位,即第32位变成第31位,第31位变成第30位,以此类推。而第1位的数值补充永远是0,无论原操作数是正数还是负数。其操作方式如下:


十进制                       二进制
12          0000 0000 0000 0000 0000 0000 0000 1100
--------------------------------------------------- 用0补足的右移操作
6           0000 0000 0000 0000 0000 0000 0000 0110


十进制                       二进制
-12             1111 1111 1111 1111 1111 1111 1111 0100(补码)
------------------------------------------------------- 用0补足的右移操作
2147483642      0111 1111 1111 1111 1111 1111 1111 1010

【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample30.htm”里的内容,其运行结果如图3.18所示。

图3.18 sample30.htm的运行结果