操作符
- 1. 一元操作符
- 1.1) 递增 / 递减操作符
- 递增和递减遵循的规则
- 1.2)一元加和减
- 2. 位操作符
- 2.1)按位非
- 2.2) 按位与
- 2.3) 按位或
- 2.4) 按位异或
- 2.5) 左移
- 2.6) 有符号右移
- 2.7) 无符号右移
- 3. 布尔操作符
- 3.1) 逻辑非
- 3.2) 逻辑与
- 3.3) 逻辑或
- 4. 乘性操作符
- 4.1) 乘法操作符
- 4.2) 除法操作符
- 4.3)取模操作符
- 5. 指数操作符
- 6. 加性操作符
- 6.1) 加法操作符
- 6.2)减法操作符
- 7. 关系操作符
- 8. 相等操作符
- 8.1)等于和不等于
- 8.2) 全等和不全等
- 9. 条件操作符
- 10. 赋值操作符
- 11. 逗号操作符
- 12. 常见操作符优先级
1. 一元操作符
1.1) 递增 / 递减操作符
前缀递增和递减
let a = 1, b = 2;
let c = ++a; // c = 2
let d = --b; // b = 1
后缀递增和递减
let a = 1;
let c = a--; // c = 1;
let d = a; // d = 0;
前后缀的主要区别:
后缀递增和递减在语句求值后才发生。
这四个操作符均可用于任何值,即可以用字符串,布尔值和对象等。
递增和递减遵循的规则
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变成数值。
- 对于字符串,如果不是有效的数值形式,则将变量的值设置为 NaN 。变量类型从字符串变成 数值。
- 对于布尔值,如果是 false,则转换为 0 再应用改变。变量类型从布尔值变成数值。
- 对于布尔值,如果是 true,则转换为 1 再应用改变。变量类型从布尔值变成数值。
- 对于浮点值,加 1或减 1。
- 如果是对象,则调用其 valueOf() 方法取得可以操作的值。对得到的 值应用上述规则。如果是 NaN,则调用 toString() 并再次应用其他规则。变量类型从对象变成数值。
1.2)一元加和减
一元加和减如果用在普通的数值运算上与数学用法没有区别。
如果将一元加和减应用到非数值,则会执行与使用 Number() 转型函数一样的类型转换:
布尔值 false 和true转换为0和1
字符串根据特殊规则进行解析
对象会调用它们的valueOf() 和 / 或 toString() 方法以得到可以转换的值
2. 位操作符
位操作符用于数值的底层操作,也就是操作内存中表示数据的比特(位)
2.1)按位非
按位非操作符用波浪符(~)表示,它的作用是返回数值的补数(即对数值取反并减一,不过位操作符运算速度更快)。
let num1 = 25; // 二进制 00000000000000000000000000011001
let num2 = ~num1; // 二进制 11111111111111111111111111100110
console.log(num2); // -26
2.2) 按位与
按位与操作符用和号(&)表示,有两个操作数。本质上,按位与就是将两个数的每一个位对齐, 然后基于真值表中的规则,对每一位执行相应的与操作(1 & 1 = 1,其他均为 0)。
let result = 25 & 3;
// 25 = 0000 0000 0000 0000 0000 0000 0001 1000
// 3 = 0000 0000 0000 0000 0000 0000 0000 0011
// = 0000 0000 0000 0000 0000 0000 0000 0001
console.log(result); // 1
2.3) 按位或
按位或操作符用管道符(|)表示,有两个操作符,遵循基于真值表中的规则,每一位执行操作(0 | 0 = 0,其他均为 1)。
let result = 25 | 3;
// 25 = 0000 0000 0000 0000 0000 0000 0001 1001
// 3 = 0000 0000 0000 0000 0000 0000 0000 0011
// = 0000 0000 0000 0000 0000 0000 0001 1011
console.log(result); // 27
2.4) 按位异或
按位异或用脱字符(^)表示,有两个操作符,遵循基于真值表中的规则,每一位执行操作(当两个相同的时候返回 0 ,其他返回 1)。
let result = 25 ^ 3;
// 25 = 0000 0000 0000 0000 0000 0000 0001 1001
// 3 = 0000 0000 0000 0000 0000 0000 0000 0011
// = 0000 0000 0000 0000 0000 0000 0001 1010
console.log(result); // 26
2.5) 左移
左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位向左移动(左移会以 0 填充这些空位,会保留它所操作数的符号)。
let oldValue = 2; // 等于二进制 10
let newValue = oldValue << 5; // 等于二进制 1000000,即十进制 64
2.6) 有符号右移
有符号右移由两个大于号(>>)表示,会将数值的所有 32位都向右移,同时保留符号(正或负)。 有符号右移实际上是左移的逆运算。
(右移后空位会出现在左侧,且在符号位之后。 ECMAScript会用符号位的值来填充这些空位,以得到完整的数值)
let oldValue = 64; // 等于二进制 1000000
let newValue = oldValue >> 5; // 等于二进制 10,即十进制 2
2.7) 无符号右移
无符号右移用 3个大于号表示(>>>),会将数值的所有 32位都向右移。
对于正数,无符号右移与有符号右移结果相同。
对于负数,与有符号右移不同,无符号右移会给空位补 0,而不管符号位是 什么。
let oldValue1 = 64; // 等于二进制 1000000
let newValue1 = oldValue1 >>> 5; // 等于二进制 10,即十进制 2
let oldValue2 = -64; // 等于二进制 11111111111111111111111111000000
let newValue2 = oldValue2 >>> 5; // 等于二进制00000111111111111111111111111110, 等于十进制 134217726
3. 布尔操作符
布尔操作符一共有 3个:逻辑非、逻辑与和逻辑或。
(均可以用于任何类型的操作数)
3.1) 逻辑非
逻辑非操作符由一个叹号(!)表示。
这个操作符始终返回布尔值,无论应用到的是什么数据类型。逻辑非操作符首先将操作数转换为布尔值,然后再对其取反。
遵循如下规则:
- 如果操作数是对象,则返回 false
- 如果操作数是空字符串,则返回 true
- 如果操作数是非空字符串,则返回 false
- 如果操作数是数值 0,则返回 true
- 如果操作数是非 0数值(包括 Infinity),则返回 false
- 如果操作数是 null,则返回 true
- 如果操作数是 NaN,则返回 true
- 如果操作数是 undefined,则返回 true
逻辑非操作符也可以用于把任意值转换为布尔值。
同时使用两个叹号(!!),相当于调用了转型函数 Boolean()。
3.2) 逻辑与
逻辑与操作符由两个和号(&&)表示,应用到两个值,遵循真值表规则(两个都为 true 的时候返回 true,其他时候返回 false)
遵循如下规则:
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有第一个操作数求值为 true 才会返回该对象
- 如果两个操作数都是对象,则返回第二个操作数
- 如果有一个操作数是 null,则返回 null
- 如果有一个操作数是 NaN,则返回 NaN
- 如果有一个操作数是 undefined,则返回 undefined
3.3) 逻辑或
逻辑或操作符由两个管道符(||)表示,遵循真值表规则(两个都为 false 的时候返回 false,其他时候返回 true)。
遵循如下规则:
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数求值为 false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数
- 如果两个操作数都是 null,则返回 null
- 如果两个操作数都是 NaN,则返回 NaN
- 如果两个操作数都是 undefined,则返回 undefined
4. 乘性操作符
4.1) 乘法操作符
乘法操作符由一个星号(*)表示,可以用于计算两个数值的乘积。
乘法操作符在处理特殊值时也有一些特殊的行为:
- 如果 ECMAScript 不能表示乘积,则返回 Infinity 或 -Infinity
- 如果有任一操作数是 NaN,则返回 NaN
- 如果是 Infinity 乘以 0,则返回 NaN。
- 如果是 Infinity 乘以非0的有限数值,则根据第二个操作数的符号返回 Infinity 或 -Infinity
- 如果是 Infinity 乘以 Infinity,则返回 Infinity
- 如果有不是数值的操作数,则先在后台用 Number() 将其转换为数值,然后再应用上述规则
4.2) 除法操作符
除法操作符由一个斜杠(/)表示,用于计算第一个操作数除以第二个操作数的商。
除法操作符针对特殊值也有一些特殊的行为:
- 如果ECMAScript不能表示商,则返回 Infinity 或 -Infinity
- 如果有任一操作数是 NaN,则返回 NaN
- 如果是 Infinity 除以 Infinity,则返回 NaN
- 如果是 0 除以 0,则返回 NaN
- 如果是非 0的有限值除以 0,则根据第一个操作数的符号返回 Infinity 或 -Infinity
- 如果是 Infinity 除以任何数值,则根据第二个操作数的符号返回 Infinity 或 -Infinity
- 如果有不是数值的操作数,则先在后台用 Number() 函数将其转换为数值,然后再应用上述规则。
4.3)取模操作符
取模(余数)操作符由一个百分比符号(%)表示。
取模操作符对特殊值也有一些特殊的行为:
- 如果操作数是数值,则执行常规除法运算,返回余数。
- 如果被除数是无限值,除数是有限值,则返回 NaN。
- 如果被除数是有限值,除数是 0,则返回 NaN
- 如果是 Infinity 除以 Infinity,则返回 NaN
- 如果被除数是有限值,除数是无限值,则返回被除数
- 如果被除数是 0,除数不是 0,则返回 0
- 如果有不是数值的操作数,则先在后台用 Number() 函数将其转换为数值,然后再应用上述规则
5. 指数操作符
ECMAScript 7新增了指数操作符,Math.pow()现在有了自己的操作符**,结果是一样的。
console.log(Math.pow(3, 2); // 9
console.log(3 ** 2); // 9
console.log(Math.pow(16, 0.5); // 4
console.log(16** 0.5); // 4
指数操作符也有自己的指数赋值操作符**=。
let squared = 3;
squared **= 2;
console.log(squared); // 9
6. 加性操作符
加性操作符有两个,加法和减法操作符。
6.1) 加法操作符
对于普通数值就是求和,对于其他的也有着特殊的规则。
如果两个操作数都是数值,加法操作符执行加法运算并根据如下规则返回结果:
- 如果有任一操作数是 NaN,则返回 NaN
- 如果是 Infinity 加 Infinity,则返回 Infinity
- 如果是-Infinity 加 -Infinity,则返回 -Infinity
- 如果是 Infinity 加 -Infinity,则返回 NaN
- 如果是+0 加 +0,则返回 +0
- 如果是-0 加 +0,则返回 +0
- 如果是-0 加 -0,则返回 -0
如果有一个操作数是字符串,则要应用如下规则:
- 如果两个操作数都是字符串,则将第二个字符串拼接到第一个字符串后面
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,再将两个字符串拼接在一起
如果有任一操作数是对象、数值或布尔值,则调用它们的 toString() 方法以获取字符串,然后再应用前面的关于字符串的规则。
对于 undefined 和 null,则调用 String() 函数,分别获取 “undefined” 和 “null”
6.2)减法操作符
对于普通的数值就是求差,也有着一些特殊的规则。
- 如果两个操作数都是数值,则执行数学减法运算并返回结果
- 如果有任一操作数是 NaN,则返回 NaN
- 如果是 Infinity 减 Infinity,则返回 NaN
- 如果是-Infinity 减-Infinity,则返回 NaN
- 如果是 Infinity 减-Infinity,则返回 Infinity
- 如果是 -Infinity 减 Infinity,则返回 -Infinity
- 如果是+0 减 +0,则返回 +0
- 如果是 +0 减 -0,则返回 -0
- 如果是 -0 减 -0,则返回 +0
- 如果有任一操作数是字符串、布尔值、null 或 undefined,则先在后台使用 Number()将其转 换为数值,然后再根据前面的规则执行数学运算。如果转换结果是 NaN,则减法计算的结果是 NaN
- 如果有任一操作数是对象,则调用其 valueOf() 方法取得表示它的数值。如果该值是 NaN,则 减法计算的结果是 NaN。如果对象没有 valueOf() 方法,则调用其 toString() 方法,然后再将得到的字符串转换为数值
7. 关系操作符
关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=)
这几个操作符都返回布尔值。
用到不同数据类型时也会发生类型转换和其他行为:
- 如果操作数都是数值,则执行数值比较
- 如果操作数都是字符串,则逐个比较字符串中对应字符的编码
- 如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较
- 如果有任一操作数是对象,则调用其 valueOf()方法,取得结果后再根据前面的规则执行比较。 如果没有valueOf()操作符,则调用toString()方法,取得结果后再根据前面的规则执行比较
- 如果有任一操作数是布尔值,则将其转换为数值再执行比较
8. 相等操作符
提供了两组操作符:
第一组是等于和不等于,它们在比较之前执行转换。
第二组是全等和不全等,在比较之前不执行转换。
8.1)等于和不等于
等于操作符用两个等于号(==)表示,如果操作数相等,则会返回 true。
不等于 操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回 true。这两个操作符都会先进行类型转换(通常称为强制类型转换)再确定操作数是否相等。
在转换操作数的类型时,相等和不相等操作符遵循如下规则:
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false 转换为 0,true 转换 为 1
- 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等
- 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法取得其原始值,再根据前面的规则进行比较
在进行比较时,这两个操作符会遵循如下规则:
- null 和 undefined 相等
- null 和 undefined 不能转换为其他类型的值再进行比较
- 如果有任一操作数是 NaN,则相等操作符返回 false,不相等操作符返回 true。记住:即使两 个操作数都是 NaN,相等操作符也返回 false,因为按照规则,NaN 不等于 NaN
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回 true。否则,两者不相等
8.2) 全等和不全等
全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数。
- 全等操作符由 3个等于号(===)表示,只有两个操作数在不转换的前提下相等才返回 true。
- 不全等操作符用一个叹号和两个等于号(!==)表示,只有两个操作数在不转换的前提下不相等才 返回 true
let result1 = ("55" == 55); // true,转换后相等
let result2 = ("55" === 55); // false,不相等,因为数据类型不同
9. 条件操作符
条件操作符由 = ?: 组成,用法如下:
let num1 = 5, num2 = 6;
let max = (num1 > num2) ? num1 : num2;
/*
相当于
let max;
if (num1 > num2) {
max = num1;
}
else {
max = num2;
}
*/
console.log(max); // 6
10. 赋值操作符
- 简单赋值(=)
- 乘后赋值(*=)
- 除后赋值(/=)
- 取模后赋值(%=)
- 加后赋值(+=)
- 减后赋值(-=)
- 左移后赋值(<<=)
- 右移后赋值(>>=)
- 无符号右移后赋值(>>>=)
这些操作符仅仅是简写语法,使用它们不会提升性能。
11. 逗号操作符
- 逗号操作符可以用来在一条语句中执行多个操作
let num1 = 1, num2 = 2, num3 = 3;
- 用逗号操作符来辅助 赋值。在赋值时使用逗号操作符分隔值,最终会返回表达式中最后一个值
let num = (5, 1, 4, 8, 0); // num 的值为 0
12. 常见操作符优先级
在这里数字小的优先级高
操作符 | 顺序 | 优先级 |
---|---|---|
小括号 | () | 1 |
一元 | ! ++ -- | 2 |
算数 | 先* / % 后 + - | 3 |
关系 | > >= < <= | 4 |
相等 | == != === !== | 5 |
位 | & ^ | | 6 |
逻辑 | 先&& 后|| | 7 |
赋值 | = | 8 |
逗号 | , | 9 |