一元操作符
只有一个值的操作符叫一元操作符
递增/递减操作符
// 前缀递增
let num = 1;
++num;
// 30
// 等价于:num = num + 1
// 前缀递减
let age = 30;
--age;
// 29,等价于age = age - 1
// 后缀递增
let num1 = 1;
num1--
// 1
// num++
// 2
前缀版和后缀版的区别在于:前缀版发生在语句被求值前,后缀版发生在语句被求值后。不过,这些在等式求值的场景下才会有区别,上述代码场景中没啥区别
let a = 2;
let b = 20;
let c = ++a + b; // 23, a = 3
let d = --a + b; // 22, a = 2
let e = a + b; // 22, a = 2
let num1 = 2;
let num2 = 20;
let num3 = num1-- + num2; // 22, num1 = 1
let num4 = num1 + num2; // 21, num1 = 1
let num5 = num1++ + num2; // 21, num1 = 2
递增和递减的前缀版和后缀版可以作用于任何值,整数、字符串、布尔值、浮点值、对象等。递增和递减操作符遵循以下规则:
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变,变量类型从字符串变为数值
- 对于字符串,如果不是有效的数值形式,则将变量的值设置为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() {
return -1;
}
};
s1++; // 值变成数值3
s2++; // 值变成NaN
b++; // 值变成数值1
f--; // 值变成0.10000000000000009(因为浮点数不精确)
o--; // 值变成-2
一元加减
由一个加号表示,放在变量前,对数值没有任何影响
let num = 25;
num = +num;
console.log(num); // 25
let num1 = 25;
num1 = -num1;
console.log(num1); // -25,一元减号将数字变为负数
应用到非数值,则会执行与使用Number()转型函数一样的类型转换:布尔值转换为0/1,字符串根据特殊规则进行解析,对象调用valueOf()和/或toString()方法得到可以转换的值
布尔操作符
逻辑非(!)
- 如果操作数是对象,则返回false
- 如果操作数是空字符串,则返回true
- 如果操作数是非空字符串,则返回false
- 如果操作数是数字0,则返回true
- 如果操作数是非0数值(包括infinity),则返回false
- 如果操作数是null,则返回true
- 如果操作数是NaN,则返回true
- 如果操作数是undefined,则返回true
同时使用两个!!,相当于调用了转型函数Boolean(),无论操作什么类型,第一个!总会返回布尔值,第二!对布尔值取反,从而给出变量真正对应的布尔值,结果和使用Boolean()是一样的
逻辑与(&&)
true && true => true
true && false => false
false && true => false
false && false => false
如果有操作数不是布尔值,则逻辑与并不一定返回布尔值:
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象
- 如果两个操作数都是对象,则返回第二个操作数
- 如果有一个操作数是null,则返回null
- 如果有一个操作数是NaN,则返回NaN
- 如果有一个操作数是undefined,则返回undefined
逻辑与是一种短路操作符,即如果第一个操作数决定了结果,则永远不会对第二个操作数求值。对逻辑与操作符来说,如果第一个操作数是false,那么第二个操作数无论是什么值,结果都不会等于true
逻辑或(||)
true && true => true
true && false => true
false && true => true
false && false => false
如果有一个操作数不是布尔值,那么逻辑与操作符不一定返回布尔值:
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数求值为false,则返回第二个操作符
- 如果两个操作数都是对象,则返回第一个操作数
- 如果有一个操作数是null,则返回null
- 如果有一个操作数是NaN,则返回NaN
- 如果有一个操作数是undefined,则返回undefined
短路特性:第一个操作数求值为true,第二个操作数则不会被求值
乘法操作符(*)
两个数相乘。
- 如果操作数都是数值,则执行常规的乘法运算,如果值很大不能表示,则返回Infinity或-Infinity
- 如果有任一操作数是NaN,则返回NaN
- 如果是Infinity乘以非0的有限数值,则根据第二个操作数的符号返回Infinity或-Infinity
- 如果是Infinity乘以Infinity,则返回Infinity
- 如果有不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则
除法操作符(/)
- 如果操作数都是数值,则执行常规的除法运算,即两个正值相除是正值,两个负值相除也是正值,符号不同的值相除得到负值。如果ECMAScript不能表示商,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果是0除以0,则返回NaN。
- 如果是非0的有限值除以0,则根据第一个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity除以任何数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果有不是数值的操作数,则先在后台用Number()函数将其转换为数值,然后再应用上述规则。
取余%
- 如果操作数是数值,则执行常规除法运算,返回余数。
- 如果被除数是无限值,除数是有限值,则返回NaN。
- 如果被除数是有限值,除数是0,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果被除数是有限值,除数是无限值,则返回被除数。
- 如果被除数是0,除数不是0,则返回0。
- 如果有不是数值的操作数,则先在后台用Number()函数将其转换为数值,然后再应用上述规则
指数操作符
原本是使用Math.pow(),在ECMAScript 7中新增了 ** 来表示。另外还有支付赋值操作符 **=
let a = 3;
a ** = 2; // 9
let b = 16;
b ** = 0.5; // 4
加号 +
主要是求和。
- 如果有任一操作数是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"
减号 -
- 如果两个操作数都是数值,则执行数学减法运算并返回结果。
- 如果有任一操作数是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()方法,然后再将得到的字符串转换为数值。
关系符
关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)和大于等于(>=),用法跟数学课上学的一样,这几个操作符都返回布尔值。
- 如果操作数都是数值,则执行数值比较。
- 如果操作数都是字符串,则逐个比较字符串中对应字符的编码。
- 如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较。
- 如果有任一操作数是对象,则调用其valueOf()方法,取得结果后再根据前面的规则执行比较。如果没有valueOf()操作符,则调用toString()方法,取得结果后再根据前面的规则执行比较。
- 如果有任一操作数是布尔值,则将其转换为数值再执行比较