JavaScript中的操作符
ECMA-262描述了一组用于操作数据值的操作符,包括算术操作符(如加号和减号)、位操作符、关系操作符和相等操作符。
一、一元操作符
只能操作一个值得操作符叫做一元操作符。
1、递增和递减操作符
- 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,在执行加减 1的操作。字符串变量变成数值常量。
- 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为NaN。字符串变量变成数值常量。
- 在应用于布尔值时,将false转换为0,将true转换为1,在执行加减 1操作。布尔值变成数值变量。
- 在应用于浮点数值时,执行加减 1的操作。
- 在应用于对象时,先调用对象的valueOf()方法,以取得一个可供操作的值。然后该值应用前述规则。如果结果是NaN,则在调用toString()方法再应用前述规则。对象变量变成数值变量。
//举个例子
let s1 = "2";
let s2 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf:function(){
return -1
}
}
s1++; //值变成数值3
s2++; //值变成NaN
b++; //值变成数值1
f--; //值变成 0.10000000000000009
o--; //值变成数值-2
2、一元加和减操作符
一元加操作符 +
- +号,放在数值前面,不会对数值产生任何影响。
- 对非数值应用: 布尔值false转换为0,true转换为1;字符串按照一组特殊的规则进行解析;对象则先调用他们的valueOf() 和(或)toString() ,在转换得到值。
一元减操作符 -
- 一元减操作符主要用于表示负数。
- 应用于非数值,遵循一元加操作符相同的规则,再将得到的值,转换为负数。
let s1 = "01";
let s2 = "1.1";
let s3 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf:function(){
return -1
}
}
s1 = -s1; //值变成了数值-1
s2 = -s2; //值变成了数值-1.1
s3 = -s3; //值变成了NaN
b = -b; //值变成了数值0
f = -f; //变成了-1.1
o = -o; //值变成了数值1
二、位操作符
位操作符用于在最基本的层次上,即按照内存中表示数值的位来存储数值。ECMAScript 中的所有数值都以IEEE-754 64位格式来存储,但位操作符并不直接操作64位的值。而是先将64位的值转换成32位的整数,然后执行操作,最后再将结果转换回64位。对于开发人员来说,由于64位存储格式是透明的,因此整个过程就像是只存在32位的整数一样。
对于有符号的整数,32位中的前31位用于表示整数的值,第32位用于表示数值的符号。0表示正数,1表示负数。这个表示符号的位叫做符号位。
正数以纯二进制格式存储,31位的每一位都表示2的幂,负数以二进制存储,但是使用的格式是二进制补码
计算一个二进制数值的补码,需要经过3个步骤,
- 求这个数值绝对值的二进制码,
- 求二进制反码,即将0替换为1,将1替换为0,
- 得到的二进制反码 加1
以-18为例,得到-18的二进制码,(十进制转二进制)
0000 0000 0000 0000 0000 0000 0001 0010 (18的二进制码)
1111 1111 1111 1111 1111 1111 1110 1101 (18二进制码的反码)
1111 1111 1111 1111 1111 1111 1110 1110 (反码+1 得到补码,即-18的二进制码)
同理,给出负数二进制码,求十进制,(二进制转十进制)
求 1111 1111 1111 1111 1111 1111 1110 0110 的十进制
首位为1,表示负数,已知负数存的是补码。则题目 减1 得到反码
1111 1111 1111 1111 1111 1111 1110 0101 (反码)
0000 0000 0000 0000 0000 0000 0001 1010 (反码取反得到正数的二进制码)
1 * 24 + 1 * 23 + 0 * 22 + 1 * 21 + 0 * 20 = 16 + 8 + 0 + 2 + 0 = 26
又因为是负数,最后结果为 -26
关于位运算,有以下几种
按位非(~)、按位与(&)、按位或(|)、按位异或(^)、左移,有符号的右移(>>)、无符号右移(>>>)
-
按位非操作符用一个 ~ 表示,执行按位非的结果就是返回数值的反码。按位非操作的本质:操作数的负值减1
let num1 = 25; //二进制 0000 0000 0000 0000 0000 0000 0001 1001 let num2 = ~num1; //二进制 1111 1111 1111 1111 1111 1111 1110 0110 console.log(num2)://-26 ~25 等同于 -25-1
-
按位与,表示有两个操作符,从本质上讲:就是将两个数值的每一位对齐,相同位置的两个数执行AND操作,当两个数值的对应位都是1时,当前位AND结果为1,任何一位是0,结果都是0。
let result = 25 & 3; console.log(result) // 1 25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 AND = 0000 0000 0000 0000 0000 0000 0000 0001 //转换为十进制 为 1 ,所以结果为1
-
按位或,两个数值的每一位对齐,有一个位是1,就返回1,只有两个位都为0才返回0。
let result = 25 | 3; console.log(result) // 27 25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 AND = 0000 0000 0000 0000 0000 0000 0001 1011 //转换为十进制 为 27 ,结果为27
-
按位异或,两个数值的每一位对齐,只有一个位是1,才返回1,否则都是0。
let result = 25 ^ 3; console.log(result) // 26 25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 AND = 0000 0000 0000 0000 0000 0000 0001 1010 //转换为十进制 为 26 ,结果为26
-
左移(<<),将数值的所有位 向左移动指定的位数,右侧多出的空位补0。 左移不会影响符号位
let oldValue= 2; //二进制 10 let newValue = oldValue << 5 ;//向左移动5位,等于二进制的 1000000,十进制的64 console.log(newValue) // 64 25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 AND = 0000 0000 0000 0000 0000 0000 0001 1010 //转换为十进制 为 26 ,结果为26
-
有符号的右移(>>) 数值向右移动,保留符号位,这样在原数值的左侧,符号位的右侧出现空位,以符号位的值进行填充。
-
无符号右移(>>>) ,会将数值的所有32位,都向右移动。对正数的无符号右移和有符号右移结果相同,对负数就不一样了。
无符号右移操作符会把负数的二进制码当成正数的二进制码,而且又因为负数是以其绝对值的补码形式表示,这样就会导致无符号右移的结果非常大。比如
let oldValue = -64 ; //二进制 11111111111111111111111111000000
let newValue = oldValue >>> 5 ;
//会把上面-64的二进制码当做正数,然后右移5位就是 00000111111111111111111111111110
//换成十进制是 134217726
三、布尔操作符 逻辑与(&&)、逻辑或(||)、逻辑非(!)
逻辑非会将它的操作数转换为一个布尔值,然后在求反,转换为布尔值为false的有:"",0,NaN,undefined,null,
如果是 !!, 同时使用两个逻辑非操作符,就会模拟Boolean() 进行布尔值类型转换。
逻辑与和逻辑非都会产生逻辑中断。
四、乘性操作符
两数相乘的一些特殊情况
如果一个操作数是NaN,结果为NaN
Infinity * 0 = NaN
Infinity * 非0数值,结果为 Infinity 或者 -Infinity
Infinity * Infinity = Infinity
如果一个操作数不是数值,会调用Number() 将其转换为数值,在应用乘法操作。
两数相除的一些特殊情况
如果一个操作数是NaN,结果为NaN
Infinity / Infinity = NaN
0 / 0 = NaN
非0有限数 / 0 ,结果为 Infinity 或者 -Infinity
非0数 / Infinity ,结果为 Infinity 或者 -Infinity
取余的一些特殊情况
Infinity % 有限大 = NaN
Infinity % Infinity = NaN
两数相加的一些特殊情况
Infinity + Infinity = Infinity
Infinity - Infinity = NaN
-Infinity - Infinity = -Infinity
+0+0 = +0
-0-0 = -0
+0-0 = +0
-
加法操作符,如果有一个操作符是对象、数值或者布尔值,则调用他们的toString()先取得字符串,在应用相应的规则。对于undefined 和 null,分别调用String()函数并取得字符串"undefined" 和 “null”
-
减法操作符,如果有一个操作符是字符串、布尔值、null或者undefined,则先调用Number()函数转成数值。如果有一个操作符是对象,则调用对象的valueOf()取得数值,如果是NaN,则减法的结果就是NaN,如果没有valueOf()方法,则调用toString()
-
关系运算符中,<,>,<=,>= , 如果有一个操作符是对象,则调用对象的valueOf(),如果没有valueOf()方法,则调用toString()
通篇内容整理于 javascript高级程序设计第三版,P36开始。