用于操作数据值的操作符,包括数学操作符(如加、减)、位操作符、关系操作符和相等操作符。
1、一元操作符
只操作一个值的操作符叫一元操作符。
递增/递减操作符
递增和递减操作符是照搬C语言,一种是放到要操作的变量前面,一种是放到要操作的变量后面。
let age = 24;
++age; //放在变量的前面,该语句相当于 age = age + 1
let money = 50;
--money; //放在变量后面,该语句相当于 money = money - 1
放在要操作的变量前面的一元操作符,都是先递增或递减,然后再执行执行其他操作。
let money = 50;
let sum = --money + 50; //这条语句,是先执行 --money,而后再继续其他运算
前缀递增和递减在语句中的优先级是相等的,因此会从左到右依次求值。
递增和递减的后缀版语法一样(分别是++和--),只不过要放在变量后面。后缀版与前缀版的主要区别在于,后缀版递增和递减在语句被求值后才发生。
let num1 = 2;
let num2 = 20;
let num3 = num1-- + num2;
let num4 = num1 + num2;
console.log(num3); //输出:22
console.log(num4); //输出:21
上述代码,在计算num3的时候,先执行'num1 + num2',这个结果为22,而后再执行'num1--'。与下面的代码效果相同:
let num1 = 2;
let num2 = 20;
//下面两句与上面的'let num3 = num1-- + num2'相同
let num3 = num1 + num2;
num1 = num1 -1;
这 4 个操作符可以作用于任何值,意思是不限于整数——字符串、布尔值、浮点值,甚至对象都可以。规则如下:
◆ 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变成数值。
◆ 对于字符串,如果不是有效的数值形式,则将变量的值设置为 NaN 。变量类型从字符串变成数值。
◆ 对于布尔值,如果是 false,则转换为 0 再应用改变。变量类型从布尔值变成数值。
◆ 对于布尔值,如果是 true,则转换为 1 再应用改变。变量类型从布尔值变成数值。
◆ 对于浮点值,加 1 或减 1。
◆ 如果是对象,则调用其(第 5 章会详细介绍的) valueOf()方法取得可以操作的值。对得到的值应用上述规则。 如果是 NaN,则调用 toString()并再次应用其他规则。变量类型从对象变成数值。
let s1 = "2";
let s2 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf() {
return -1;
}
};
s1++; // 值变成数值 3
s2++; // 值变成 NaN
b++; // 值变成数值 1
f--; // 值变成 0.10000000000000009(因为浮点数不精确)
o--; // 值变成-2
一元加和减
一元加由一个加号( +)表示,放在变量前头,对数值没有任何影响。
let num = 25;
num = +num;
console.log(num); // 25
如果将一元加应用到非数值,则会执行与使用 Number()转型函数一样的类型转换。
布尔值 false和 true 转换为 0 和 1,字符串根据特殊规则进行解析,对象会调用它们的 valueOf()和/或 toString()方法以得到可以转换的值。
let s1 = "01";
let s2 = "1.1";
let s3 = "z";
let b = false;
let f = 1.1;
let o = {
valueOf() {
return -1;
}
};
s1 = +s1; // 值变成数值 1
s2 = +s2; // 值变成数值 1.1
s3 = +s3; // 值变成 NaN
b = +b; // 值变成数值 0
f = +f; // 不变,还是 1.1
o = +o; // 值变成数值-1
上述代码是一元加号的用法,一元减号会将其变成相对应的负值。
2、位操作符
操作内存中表示数据的比特(位)。ECMAScript中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为 64位。
有符号整数使用 32 位的前 31 位表示整数值。第 32 位表示数值的符号,如 0 表示正, 1 表示负。这一位称为符号位。它的值决定了数值其余部分的格式。
Ⅰ. 按位非
按位非操作符用波浪符( ~)表示,它的作用是返回数值的一补数。
let num1 = 25; // 二进制 00000000000000000000000000011001
let num2 = ~num1; // 二进制 11111111111111111111111111100110
console.log(num2); // -26
按位非操作符作用到了数值 25,得到的结果是26。由此可以看出,按位非的最终效果是对数值取反并减 1。
Ⅱ. 按位与
按位与操作符用和号( &)表示,有两个操作数。本质上,按位与就是将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的与操作。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
按位与操作在两个位都是 1 时返回 1,在任何一位是 0 时返回 0。
Ⅲ. 按位或
按位或操作符用管道符( |)表示,同样有两个操作数。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
按位或操作在至少一位是 1 时返回 1,两位都是 0 时返回 0。
Ⅳ. 按位异或
按位异或用脱字符( ^)表示,同样有两个操作数。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
按位异或,只有两个数值不一样的时候,结果才为1。
Ⅴ. 左移
左移操作符用两个小于号( <<)表示,会按照指定的位数将数值的所有位向左移动。
let oldValue = 2; // 等于二进制 10
let newValue = oldValue << 5; // 等于二进制 1000000,即十进制 64
Ⅵ. 有符号右移
有符号右移由两个大于号( >>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。
let oldValue = 64; // 等于二进制 1000000
let newValue = oldValue >> 5; // 等于二进制 10,即十进制 2
右移后空位会出现在左侧,且在符号位之后。ECMAScript 会用符号位的值来填充这些空位。
Ⅶ. 无符号右移
无符号右移用 3 个大于号表示( >>>),会将数值的所有 32 位都向右移。对于正数,无符号右移与有符号右移结果相同。
对于负数,有时候差异会非常大。与有符号右移不同,无符号右移会给空位补 0,而不管符号位是什么。无符号右移操作符将负数的二进制表示当成正数的二进制表示来处理。因为负数是其绝对值的二补数,所以右移之后结果变
得非常之大。
let oldValue = -64; // 等于二进制 11111111111111111111111111000000
let newValue = oldValue >>> 5; // 等于十进制 134217726
注:可以参考计算机组成原理中的相关内容
3、布尔操作符
布尔操作符一共有 3 个:逻辑非、逻辑与和逻辑或。
Ⅰ. 逻辑非
逻辑非操作符由一个叹号( !)表示,可应用给 ECMAScript 中的任何值。 这个操作符始终返回布尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转换为布尔值,然后再对其取反。
❉ 如果操作数是对象,则返回 false。
❉ 如果操作数是空字符串,则返回 true。
❉ 如果操作数是非空字符串,则返回 false。
❉ 如果操作数是数值 0,则返回 true。
❉ 如果操作数是非 0 数值(包括 Infinity),则返回 false。
❉ 如果操作数是 null,则返回 true。
❉ 如果操作数是 NaN,则返回 true。
❉ 如果操作数是 undefined,则返回 true。
console.log(!false); // true
console.log(!"blue"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!12345); // false
逻辑非操作符也可以用于把任意值转换为布尔值。同时使用两个叹号( !!),相当于调用了转型函数 Boolean()。无论操作数是什么类型,第一个叹号总会返回布尔值。第二个叹号对该布尔值取反,从而给出变量真正对应的布尔值。
console.log(!!"blue"); // true
console.log(!!0); // false
console.log(!!NaN); // false
console.log(!!""); // false
console.log(!!12345); // true
Ⅱ. 逻辑与
逻辑与操作符由两个和号( &&)表示,应用到两个值。
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
逻辑与操作符可用于任何类型的操作数,不限于布尔值。如果有操作数不是布尔值,则逻辑与并不一定会返回布尔值。
◈ 如果第一个操作数是对象,则返回第二个操作数。
◈ 如果第二个操作数是对象,则只有第一个操作数求值为 true 才会返回该对象。
◈ 如果两个操作数都是对象,则返回第二个操作数。
◈ 如果有一个操作数是 null,则返回 null。
◈ 如果有一个操作数是 NaN,则返回 NaN。
◈ 如果有一个操作数是 undefined,则返回 undefined。
逻辑与操作符是一种短路操作符,意思就是如果第一个操作数决定了结果,那么永远不会对第二个
操作数求值。
Ⅲ. 逻辑或
逻辑或操作符由两个管道符( ||)表示。
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
与逻辑与类似,如果有一个操作数不是布尔值,那么逻辑或操作符也不一定返回布尔值。
◈ 如果第一个操作数是对象,则返回第一个操作数。
◈ 如果第一个操作数求值为 false,则返回第二个操作数。
◈ 如果两个操作数都是对象,则返回第一个操作数。
◈ 如果两个操作数都是 null,则返回 null。
◈ 如果两个操作数都是 NaN,则返回 NaN。
◈ 如果两个操作数都是 undefined,则返回 undefined。
同样与逻辑与类似,逻辑或操作符也具有短路的特性。只不过对逻辑或而言,第一个操作数求值为true,第二个操作数就不会再被求值了。