ECMA-262描述了一组可用于操作数据值的 操作符 ,包括数学操作符、位操作符、关系操作符、相等操作符等
1、一元操作符
只操作一个值的操作符
- 递增/递减操作符
//前缀版
//无论是前缀递增还是前缀递减操作符,变量的值都会在语句被求值之前改变
let age = 20;
let otherAge = --age + 2;
console.log(age);//19
console.log(otherAge);//21
//后缀版
//无论是后缀递增还是后缀递减操作符,变量的值都会在语句被求值之后改变
let age = 20;
let otherAge = age-- + 2;
console.log(age);//19
console.log(otherAge);//22:
//注意:如果age不是数值,操作符会将age变量转为数值在递减
- 一元加减符
//+放在数值前对数值没有影响,-放在数值前会转为负数
let num = 5;
+5;//5
-5;//-5
//一元加减用于非数值前时,会执行Number()转型函数一样的类型转换
let s1 = '001';
-s1 ; // -1
+'true';//1
2、位操作符
用于操作数值的底层操作,也就是操作表示数据的比特(位)。
//正值以真正的二进制格式储存
18
![2进制](https://img-blog.csdnimg.cn/20210112223600532.png#pic_center)
//二补数
-18
1. 绝对值二进制表示
0000 0000 0000 0000 0000 0000 0001 0010
2. 找到数值的一补数
1111 1111 1111 1111 1111 1111 1110 1101
3. 给补数加1
1111 1111 1111 1111 1111 1111 1110 1110
-18的二进制表示为11111111111111111111111111101110
//ECMAScript会帮我们记录这些信息,在把负值输出为一个二进制字符串时,我们会得到一个加了减号的绝对值
let num = -18;
num.toString(2);// - "10010"
//负值则以**二补数**的二进制编码储存
按位非
(~)表示,它的作用返回数值的一补数
//按位非最终结果时数值取反并-1
//规则:1 ——> 0 , 0 ——> 1
let num = 25; //二进制 00000000000000000000000011001
let num2 = ~num;//二进制 11111111111111111111111100110
console.log(num2);//-26
按位与
(&)符号表示,两个操作数,本质上是将两个数的每一位对齐,然后基于真值规则,对应每一位执行相应的与操作
第一位 | 第二位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
let rs = 25 & 3 ;
25 = 0000 0000 0000 0000 0000 0000 0001 1001
3 = 0000 0000 0000 0000 0000 0000 0000 0011
rs = 0000 0000 0000 0000 0000 0000 0000 0001
console.log(rs);// 1
按位或
( | )表示,两个操作数。
第一位 | 第二位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
let rs = 25 & 3 ;
25 = 0000 0000 0000 0000 0000 0000 0001 1001
3 = 0000 0000 0000 0000 0000 0000 0000 0011
rs = 0000 0000 0000 0000 0000 0000 0001 1011
console.log(rs); //27
按位异或
( ^ )同样有两个操作数
第一位 | 第二位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
let rs = 25 & 3 ;
25 = 0000 0000 0000 0000 0000 0000 0001 1001
3 = 0000 0000 0000 0000 0000 0000 0000 0011
rs = 0000 0000 0000 0000 0000 0000 0001 1010
console.log(rs); //26
左移
(<<)按照指定的位数将数值的所有位向左移
//左移会保留操作数值的符号
let oldValue = 2; //二进制 10
let newValue = oldValue << 5;//二进制 1000000 即10进制64
右移
(>>)有符号的右移,(>>>)无符号的右移。对正数而言有无符号的右移无区别,但对于负数而言区别会非常大
//有符号右移(>>)
let oldValue = 64; //等于二进制 1000000
let newValue = oldValue >>> 5 ; //等于二进制 10 即十进制 2
//无符号的右移(>>>)
//将负数的二进制当成正数的二进制处理。因为负数是其绝对值的二补数,所以右移后差距非常大
let oldValue = -64; //二进制 11111111111111111111111111000000
let newVale = ooldValue>>>5;//二进制 00000111111111111111111111111110 十进制 13421726
布尔操作符
- 逻辑非
( ! )表示,可应用任何值。逻辑非首先将值转化为布尔值,然后再取反
//遵守如下规则
- 对象 -> false
- '' -> true
- 'x' -> false (x表示任意非空字符)
- 0 -> true
- 非0 -> false (包括 Infinity)
- null -> true
- NaN -> true
- undefined -> true
// !!相当于调用了转型函数
!!'0' ; // false
!null ; // true
- 逻辑与
(&&)表示,应用到两个值
第一个值 | 第二个值 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
//返回值并不一定都是布尔值,遵循如下规则
- 第一个是对象,直接返回第二个操作数
- 第二个值为对象,则第一个值判断为true才返回对象
- 两个都是对象,则返回第二个操作数
- 有一个值为null,则返回null
- 有一个值为NaN,则返回NaN
- 有一个值为undefined,则返回undefined
//逻辑与操作符是一种短路操作符。如果第一个操作决定了结果就不去对第二个操作数求值
'' && 22; // '' 操作数1判断为false,结果为false,直接返回操作数1
1 && ''; // '' 操作数1判断为true,结果为操作数2判断,直接返回操作数2
逻辑或
( || )表示,与逻辑与类似
第一个值 | 第二个值 | 结果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
//遵循如下规则
- 第一个是对象,直接返回第1个操作数
- 第二个值为对象,则第一个值判断为false才返回对象
- 两个都是对象,则返回第1个操作数
- 有一个值为null,则返回null
- 有一个值为NaN,则返回NaN
- 有一个值为undefined,则返回undefined
//同样具有短路特性
'' || 22 ;// 22 第一个操作数判断为false,直接返回第二个操作数
22 || '' ;// 22 第一个数判断为true,直接返回第一个操作数
3、 称性操作符
针对数值的操作符,不是数值会先按规则转化为数值再按规则运算
(*)表示,用于计算两个数乘积
//遵循如下规则
- 正*正=正,正*负=负,负*负=负,不能表示乘积则返回 ±Infinity
- 有一个数是NaN,则返回NaN
- Infinity * 0 ;// NaN;
- Infinity * (非0有限数),则根据第一个操作数的符号放回±Infinity
- Infinity * Infinity ;// Infinity;
(/)表示,计算一个操作数除以第二个操作数的商
//规则如下
- 正/正=正,正/负=负,负/负=负,不能表示乘积则返回 ±Infinity
- Infinity / Infinity ;// NaN
- NaN / NaN ;// NaN
- 0 / 0 ; // NaN
- 非0 / 0 ; //根据第二个操作数符号返回 ±Infinity
- Infinity / ±任意数 ;// ±Infinity
(%)表示,除法运算后的余数
let rs = 26 % 5 ; // 1
//规则如下
- 操作数是数值,则执行常规除法运算,返回余数
- 被除数是无限值,除数是有限制,返回 NaN // Infinity % 有限值; NaN
- 被除数是有限值,除数是0,返回 NaN // 有限值 % 0 ; NaN
- Infinity % Infinity; // NaN
- 被除数是有限值,除数是无限制,返回被除数 // 有限值 % Infinity ; 有限值
- 被除数0,除数不是0,则返回0 // 0 % 不是0 ; 0
4、指數操作符
EMACscript新增操作符,Math.pow()现在有自己的操作符 ( ** )
//指數操作符
Math.pow(3 , 2 ) ;// 9
3 ** 2 ;// 9
//指数赋值操作符 **=
let num = 3 ;
num **= 2 ;
console.log(nnm); // 9
5、加性操作符
用于求两数之和
//遵循如下规则
- NaN + 任意数; //则返回NaN
- Infinity + Infinity ; // Infinity
- -Infinity + -Infinity;// -Infinity
- Infinity + -Infinity; // NaN
- +0 + +0; // +0
- -0 + +0; // +0
- -0 + -0; // -0
- 两个数位字符串,则作字符串拼接
- 一个数为字符串,则将另一个数转化为字符串再拼接
'5' + 2 + 1; // '521'
2 + 1 + '5' ; // '35'
+'5' + 2 ;// 7
6、减法操作符
//遵循如下规则
- NaN + 任意数; //则返回NaN
- Infinity - Infinity ; // Infinity
- Infinity - -Infinity;// -Infinity
- -Infinity - -Infinity; // NaN
- +0 - +0; // +0
- +0 - -0; // -0
- -0 - -0; // +0
- 任意操作数是字符串、布尔值、null 或 undefined,则先转化为数值再按规则计算。若转化为NaN,计算结果也为NaN
- 如果任意操作数是对象,调用其valueOf(),取得表示它的数值。该值为NaN则计算返回NaN
7、关系操作符
用于比较两个值的操作,包括大于、小于,大于等于,小于等于;跟数学课上的一样。操作符返回布尔值
//遵守如下规则
- 操作数都为数值,正常比较
- 任意一操作数为数值,则另一个操作数转化为数值在做比较
- 都是字符串,则逐个比较对应字符串的编码
- 任意操作数为布尔值,则转化为数值在执行比较
- 任意操作数为对象,则调用其valueOf()方法,取得结果再按上述规则比较
//比较两个字符串
'Brick' < 'alphabet'; //true 编码 B:66 a:97
8、相等操作符
- 等于和不等于
等于(==),如果操作数相等返回true,否则返回false;不等于(!=)与前者类似;两个操作符都会先进行强制类型转换,在确定操作数是否相等
//遵循规则如下
- 任意一方为布尔值,则将其转换为数值再进行比较
- 一个是字符串,另一个实数值,将字符串转换为数值,再比较
- 一个是对象,另一个不是,调用对象valueOf取原始值再按规则比较
- null == undefined ; //true
- null、undefined 类型不能转换为其他类型再比较
- 任意操作数为NaN,==返回false,!=返回true
- 两个数都是对象,如果两个操作数都指向同一个对象则相等符号返回 true
- 全等与不全等
(=== | !==)只有操作符不转换的情况下相等才返回 true
'5' === 5;//false
true === 1;//false
1 === 1 ;//true
9、条件操作符
用途最广的操作符之一(也称三目运算符)
//语法
//条件成立则执行表达式1,否则执行表达式2
条件?表达式1:表达式2;
//用法
let x = 5;
let flag = x>5? x -=5 :x += 5 ;//执行表达式2 返回 10
//可嵌套使用
flag = x>10? (x>5? x+=5: x-=5): x-= 10;
10、赋值操作符
赋值的简写操作
//只是简写,不会提高性能
- *=
- /=
- +=
- -=
- %=
- <<=
- >>=
- >>>=
//实例
let num = 2;
num *= 3;//6
//等价于
let num = 2;
num = num * 3;//6
//其他操作符类似
11、逗号操作符
常用于声明多个变量
var a = 123,
b = false,
c = 555;