⭐ 作者简介:码上言
⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程
⭐专栏内容:个人博客系统
⭐我的文档网站:http://xyhwh-nav.cn/
⭐微信公众号:码上言
操作符
ECMA-262描述了一组可用于操作数据值的操作符,包括数学操作符(如加、减)、位操作符、关系操作符和相等操作符等。
1. 位操作符
位操作符用于数值的底层操作,也就是操作内存中表示数据的比特(位)。ECMAScript中的所有数值都以IEEE 75464位格式存储,但位操作并不直接应用到64位表示,而是先把值转换为32位整数,再进行位操作,之后再把结果转换为64位。对开发者而言,就好像只有32位整数一样,因为64位整数存储格式是不可见的。既然知道了这些,就只需要考虑32位整数即可。
有符号整数使用32位的前31位表示整数值。第32位表示数值的符号,如0表示正,1表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式。负值以一种称为二补数(或补码)的二进制编码存储。一个数值的二补数通过如下 3 个步骤计算得到:
- 确定绝对值的二进制表示(如,对于-18,先确定 18 的二进制表示)
- 找到数值的一补数(或反码),换句话说,就是每个 0 都变成 1,每个 1 都变成 0
- 给结果加 1。
1.1. 按位非
按位非操作符用波浪符(~)表示,它的作用是返回数值的一补数。
在JavaScript中,按位非操作符用~
表示。它对操作数的每一位执行反转(0变为1,1变为0)。按位非操作符应用于一个整数时,将其转换为32位二进制数,然后对每一位进行反转。
例如:
let num = 5; // 二进制表示为 00000000000000000000000000000101
let result = ~num; // 结果为 -6
请注意,按位非操作会将操作数从正数转换为负数,并减去1。因此,对于正整数n,按位非操作的结果为-(n+1)。
在实际应用中,按位非操作常用于位操作和某些算法中,对于一般的编程任务,它可能不常用。
1.2. 按位与
按位与操作符用和号(&)表示,有两个操作数。本质上,按位与就是将两个数的每一个位对齐,
然后基于真值表中的规则,对每一位执行相应的与操作。
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
按位与操作在两个位都是 1 时返回 1,在任何一位是 0 时返回 0。
1.3. 按位或
按位或操作符用管道符(|)表示,同样有两个操作数。按位或遵循如下真值表:
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
按位或操作在至少一位是 1 时返回 1,两位都是 0 时返回 0。
1.4. 按位异或
按位异或用脱字符(^)表示,同样有两个操作数。下面是按位异或的真值表:
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
按位异或与按位或的区别是,它只在一位上是 1 的时候返回 1(两位都是 1 或 0,则返回 0)。
1.5. 左移
左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动。
let oldValue = 2; // 等于二进制 10
let newValue = oldValue << 5; // 等于二进制 1000000,即十进制 64
左移会保留它所操作数值的符号。比如,如果2 左移 5 位,将得到64,而不是正 64。
1.6. 有符号右移
有符号右移由两个大于号(>>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。
let oldValue = 64; // 等于二进制 1000000
let newValue = oldValue >> 5; // 等于二进制 10,即十进制 2
1.7. 无符号右移
无符号右移用 3 个大于号表示(>>>),会将数值的所有 32 位都向右移。对于正数,无符号右移与
有符号右移结果相同。
let oldValue = 64; // 等于二进制 1000000
let newValue = oldValue >>> 5; // 等于二进制 10,即十进制 2
对于负数,有时候差异会非常大。与有符号右移不同,无符号右移会给空位补 0,而不管符号位是什么。对正数来说,这跟有符号右移效果相同。但对负数来说,结果就差太多了。无符号右移操作符将负数的二进制表示当成正数的二进制表示来处理。因为负数是其绝对值的二补数,所以右移之后结果变得非常之大。
let oldValue = -64; // 等于二进制 11111111111111111111111111000000
let newValue = oldValue >>> 5; // 等于十进制 134217726