算术运算符
- JS共提供10个算术运算符:
- 加法运算符:
x + y - 减法运算符:
x - y - 乘法运算符:
x * y - 除法运算符:
x / y - 指数运算符:
x ** y - 余数运算符:
x % y - 自增运算符:
++x或者x++ - 自减运算符:
--x或者x-- - 数值运算符:
+x - 负数值运算符:
-x
- 加法运算符:
加减乘除 + - * /
加法运算符是在运行时决定到底是相加还是字符串拼接。而- * /则不会如此,它们的规则是两侧运算子一律转为数值,再进行相应的运算。
false + 'a' // 'falsea' 有一个是字符串时,则另一个会转成字符串后再连
true + true // 2
原始值相加: 运算子如果有字符串则是字符串拼接,如果没有则转为数值,隐式调用Number()然后相加。
true + true // 2
true + null // 0
null + undefined // NaN
true + 3.14 // 4.140000000000001(精度问题)
true + '3.14' // 'true3.14'
引用值相加:运算子如果是引用值,会先转为原始值然后再相加。先调用valueOf(),如果返回的还是对象,再调用toString()。再进行字符串拼接。
var obj = { p: 1 };
obj + 2 // "[object Object]2"
// 1. 先调用对象的 valueOf()方法,对象的valueOf()总是返回对象自身
obj.valueOf() // {p: 1}
// 2. 再调用对象的toString方法,将其转为字符串
obj.valueOf().toString() // "[object Object]"
var arr = [1,2,3];
arr + 1 // '1,2,31'
arr + true // '1,2,3true'
// 先调用valueOf(),后调用toString()
arr.valueOf() // [1, 2, 3]
arr.valueOf().toString() // '1,2,3'
- 浮点数参与运算会出现精度问题,需要转成整数然后再除回来。
/**
* 参数:数字、n次幂
*/
function formatNum(num, n){
var mul = parseInt(num * Math.pow(10, n)); // 将小数乘以10的n次幂(转为整数)并取整
return mul / Math.pow(10, n); // 再除以10的n次幂,得到的结果为正确的结果
}
var total = 0.1 + 0.2;
console.log(total === 0.3); // false
var res = formatNum(total, 1);
console.log(res === 0.3) // true
余数 %
12 % 5 // 2
3 % 4 // 3
// 运算结果的正负号由第一个运算子的正负号决定
-1 % 1 // -1
1 % -5 // 1
自增自减 ++ --
- 前置递增(递减):先自加(自减),后返回值;后置递增(递减):先返回值,后自加、自减。
- 此运算符会将运算子首先转为数值,与
Number()函数的作用相同,然后再自增或自减。
var x = true;
x++; // Number(true) => 1
x // 2
正负 + -
- 此运算符会将运算子转为数值,与
Number()函数的作用相同。
+true; // 1 Number(true) => 1
-true; // -1 Number(true) => 1 => -1
-null // -0 Number(null) => 0
+[] // 0 Number([]) => 0
+undefined // NaN Number(undefined) => NaN
+{} // NaN Number({}) => NaN
指数 **
- 前一个运算子是底数,后一个运算子是指数。当多个指数运算符连用时,先进行最
右边的计算。
3 ** 1 // 3 3
3 ** 2 // 9 3 * 3
3 ** 3 // 27 3 * 3 * 3
2 ** 3 ** 2 // 521 相当于 2 ** (3 ** 2)
赋值 = += -= *= /= %= **=
// 等同于 x = x + y
x += y
// 等同于 x = x - y
x -= y
// 等同于 x = x * y
x *= y
// 等同于 x = x / y
x /= y
// 等同于 x = x % y
x %= y
// 等同于 x = x ** y
x **= y
{} 参与运算的情况
[] + {} // '[object Object]'
// 解析流程如下:
// 1. [].valueOf().toString() === ''
// 2. ({}).valueOf().toString() === '[object Object]'
// 3. '' + '[object Object]' === '[object Object]'
- 以上解析结果没问题,但如果把
{}放在语句开头呢?
{} + [] // 0
- 出问题了,为什么等于0?这是因为一条语句如果以
{}开头,JS会把{}解析成一个空的代码块,并忽略它。相当于直接计算+[],[]转为了空串,+又把空串转为了数字,所以结果为0。
{} + {} // NaN
- 还是以上原因,相当于直接计算
+{},Number({}) === NaN,所以结果为NaN。
({}) + [] // '[object Object]'
({}) + {} // '[object Object][object Object]'
// 解析流程如下:
// 1. ({}).valueOf() === {}
// 2. ({}).toString() === '[object Object]'
// 3. '[object Object]' + '[object Object]' === '[object Object][object Object]'
- 用圆括号将
{}包起来,让JS将这段解析成一个表达式就可以正常得到理想中的结果了。
{} - 1 // -1 相当于直接计算 -1
({}) - 1 // NaN 相当于 '[object Object]' - 1
比较运算符
- JS提供了8个比较运算符:
- 大于运算符
x > y - 小于运算符
x < y - 大于等与运算符
x >= y - 小于等于运算符
x <= y - 相等运算符
== - 严格相等运算符
=== - 不等运算符
!= - 严格不等运算符
!==
- 大于运算符
大于 小于 大于等于 小于等于 > < >= <=
- 两个
字符串比较的是Unicode字符集码点的大小,如果第一个字符相等,再依次对比。
'cat' > 'dog' // false
'cat' > 'catalog' // false
'大' > '小' // false '大'的码点为22823;'小'的码点为23657
'10' > '11' // false '1'的码点为49,第一位相等,开始比较第二位:'0'的码点为48,小于'1'
- 两个
原始值比较,先转成数值,调用Number()函数后再比较。
5 > '4' // true Number('4') => 4
true > false // true Number(true) => 1 Number(false) => 0
2 > true // true
2 > '2a' // false Number('2a') => NaN
2 > undefined // false Number(undefined) => NaN
2 > null // true Number(null) => 0
NaN与任何值比较都不相等,包括自身。
如果有对象,会转为原始值。先调用valueOf(),如果返回的还是对象,再调用toString()。如果两个值都是字符串类型,则直接比较Unicode码点;如果不是,则转为数值后再比较。
var x = [2];
x > '11' // true
// 等同于 [2].valueOf().toString() > '11'
// '2' > '11',开始比较Unicode码点
var y = [2];
y > 1; // true
// 等同于 [2].valueOf().toString() > 1
// Number('2') > 1
// 2 > 1 true
var obj = {};
obj > '1' // true
// 等同于 {}.valueOf().toString() > '[object Object]'
// 即 '[object Object]' > '1',开始比较Unicode码点
严格相等 ===
没有类型转换,如果两个值的类型不一样则直接返回false。- 只有类型相同并且值也相同才返回
true。
1 === '1' // false
true === 'true' // false
1 === 1 // true
+0 === -0 // true 特殊
undefined === undefined // true
null === null // true
NaN与任何值比较都不相等,包括自身。
- 两个对象(对象、数组、函数)比较时,比较的是他们
是否指向同一个内存地址。
{} === {} // false
[] === [] // false
(function(){} === function(){}) // false
var obj = {};
var obj2 = obj;
obj2 === obj // true obj 和 obj2指向的同一个内存地址
严格不相等 !==
- !==的算法是
先求===的结果,然后取反。
1 !== '1' // true 相当于: !(1 === '1')
相等运算符 ==
- 比较
不同类型的数据时,先进行类型转换,再用严格相等比较。 - 比较
不同类型的数据时,先进行类型转换,再用严格相等比较。 - 比较
不同类型的数据时,先进行类型转换,再用严格相等比较。 原始值类型转换:Number()。
1 == true // true Number(true) => 1
0 == false // true Number(false) => 0
'true' == true // Number('true') => NaN Number(true) => 1
'' == 0 // true Number('') => 0
'123' == 123 // true
对象与原始值比较的类型转换:先调用valueOf(),如果返回的还是对象,再调用toString(),得到的值类型如果与原始值类型相同,则直接调用严格相等比较。如果类型不同,则再调用Number()。
[1] == 1 // true
// 1. [1].valueOf().toString() => '1'
// 2. Number('1') => 1
// 3. 1 === 1 两个原始值类型相同,直接严格相等比较,返回 true
[1,2] == '1,2' // true
// 1. [1,2].valueOf().toString() => '1,2'
// 2. '1,2' === '1,2' 两个原始值类型相同,直接严格相等比较,返回 true
[1] == true // true
// 1. [1].valueOf().toString() => '1'
// 2. Number('1') => 1
// 3. Number(true) => 1
// 4. 1 === 1 两个原始值类型相同,直接严格相等比较,返回 true
- null 和 undefined
undefined == undefined // true
null == null // true
undefined == null // true
false == null // false
false == undefined // false
0 == null // false
0 == undefined // false
undefined和null只有与自身比较,或者互相比较时,才会返回true;与其他任何类型的值比较时,都返回false。
不相等运算符 !=
- 先求
相等运算符的结果,然后取反。
1 != '1' // false 相当于 !(1 == '1')
逻辑运算符
- 用于将表达式转为boolean,一共包含4个:
- 与运算符
&& - 或运算符
|| - 非运算符
! - 三元运算符
?:
- 与运算符
0、null、undefined、""、NaN、false转为boolean值都是false。
与运算符 &&
- 两侧都为
true返回true,一侧为false返回false。
1 && 0 // 0
0 && 1 // 0
1 && console.log(123); //123
&& 遇 false 或最后一个值时直接返回该值。
或运算符 ||
- 两侧都为
false返回false,一侧为true返回true。
1 || 0 // 1
0 || 1 // 1
0 || false || 1; // 1
|| 遇 true 或最后一个值时直接返回该值。
非运算符 !
- 将boolean值转为相反值。
!123 // false
!"" // true
!!123 // true 相当于把一个数据变成 boolean 数据
三元运算符 ?:
- 三元运算符是JS中唯一一个需要三个运算子的运算符。
't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"
void 运算符
- 用于执行一个表达式,但是不返回任何值,也可以说是返回
undefined。
void(1+1) // undefined
- 一般用于
<a>标签上,防止点击后网页跳转。
<a href="javascript:void(0);" οnclick="alert('text...')"> </a>
逗号运算符 ,
- 用于对两个表达式求值,并返回后一个表达式的值。
var x = 0;
var y = (x++, 10); // 先计算x++,然后返回10,给y赋值
x // 1
y // 10
// 逗号运算符的一个用途是,在返回一个值之前,进行一些辅助操作
var value = (console.log('Hi!'), true); // Hi!
value // true