算术运算符
JavaScript 共提供10个算术运算符,用来完成基本的算术运算。
加法运算符:x + y
减法运算符: x - y
乘法运算符: x * y
除法运算符:x / y
指数运算符:x ** y
余数运算符:x % y
自增运算符:++x 或者 x++
自减运算符:--x 或者 x--
数值运算符: +x
负数值运算符:-x
减法、乘法、除法运算法比较单纯,就是执行相应的数学运算。
比较运算符
JavaScript 一共提供了8个比较运算符。
>
大于运算符
<
小于运算符
<=
小于或等于运算符
>=
大于或等于运算符
==
相等运算符 比较两个值是否相等
===
严格相等运算符 比较是否为同一个值,需要考虑数据类型。
!=
不相等运算符
!==
严格不相等运算符 比较两个值是否不相等,同时考虑数据类型。
这八个比较运算符分成两类:相等比较和非相等比较。两者的规则是不一样的,对于非相等的比较,算法是先看两个运算子是否都是字符串,如果是的,就按照字典顺序比较(实际上是比较 Unicode 码点);否则,将两个运算子都转成数值,再比较数值的大小。
undefined和null只有与自身比较,或者互相比较时,才会返回true;与其他类型的值比较时,结果都为false。
布尔运算符
JavaScript 提供了4个布尔运算符,用来做逻辑运算。
!
非运算符
&&
与运算符
` | ` 或运算符 |
---|
??
空值合并运算符
二进制位运算符
二进制位运算符用于直接对二进制位进行计算,一共有7个。
二进制或运算符(or):符号为 | ,表示若两个二进制位都为0,则结果为0,否则为1。 |
---|
二进制与运算符(and):符号为&,表示若两个二进制位都为1,则结果为1,否则为0。
二进制否运算符(not):符号为~,表示对一个二进制位取反。
异或运算符(xor):符号为^,表示若两个二进制位不相同,则结果为1,否则为0。
左移运算符(left shift):符号为<<
右移运算符(right shift):符号为>>
头部补零的右移运算符(zero filled right shift):符号为>>>
这些位运算符直接处理每一个比特位(bit),所以是非常底层的运算,好处是速度极快,缺点是很不直观,许多场合不能使用它们,否则会使代码难以理解和查错。
有一点需要特别注意,位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。另外,虽然在 JavaScript 内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。
i = i | 0;
上面这行代码的意思,就是将i(不管是整数或小数)转为32位整数。
利用这个特性,可以写出一个函数,将任意数值转为32位整数。
function toInt32(x) {
return x | 0;
}
上面这个函数将任意值与0进行一次或运算,这个位运算会自动将一个值转为32位整数。下面是这个函数的用法。
toInt32(1.001) // 1
toInt32(1.999) // 1
toInt32(1) // 1
toInt32(-1) // -1
toInt32(Math.pow(2, 32) + 1) // 1
toInt32(Math.pow(2, 32) - 1) // -1
上面代码中,toInt32可以将小数转为整数。对于一般的整数,返回值不会有任何变化。对于大于或等于2的32次方的整数,大于32位的数位都会被舍去。
其他运算符,运算顺序
void运算符
void运算符的作用是执行一个表达式,然后返回undefined。
void 0 // undefined
void(0) // undefined
上面代码中,void运算符的作用就是返回undefined。
void运算符的一个用途是,在链接多个表达式时,保证每个表达式都返回undefined,而不是最后一个表达式的返回值。
void (0, 1, 2); // undefined
上面代码中,void运算符将逗号运算符(comma operator)的返回值,变成了undefined。
void运算符的另一个用途是,在超链接中,防止用户点击后,页面跳转。
<a href="javascript: void(0);">点击后不会跳转</a>
上面代码中,点击超链接后,不会发生跳转,因为void运算符的返回值是undefined。
逗号运算符
逗号运算符(comma operator)用于对两个表达式求值,并返回后一个表达式的值。
a = (1, 2, 3);
// 3
上面代码中,逗号运算符返回了3。
运算顺序
JavaScript 运算符的运算顺序是从左到右,但是有一些运算符的优先级较高,会先于其他运算符执行。
运算符的优先级
JavaScript 运算符的优先级从高到低,如下表所示。
运算符 | 描述 | |
---|---|---|
() | 圆括号 | |
delete , void , typeof , ++ , -- , + , - , ~ , ! | 一元运算符 | |
* , / , % | 乘法、除法、取余 | |
+ , - | 加法、减法 | |
<< , >> , >>> | 左移、右移、头部补零的右移 | |
< , <= , > , >= | 小于、小于或等于、大于、大于或等于 | |
== , != , === , !== | 相等、不相等、严格相等、严格不相等 | |
& | 位与 | |
^ | 位异或 | |
` | ` | 位或 |
&& | 逻辑与 | |
` | ` | 逻辑或 |
数据类型转换
强制类型转换
number类型的强制类型转换
number类型的强制类型转换,使用Number函数。
Number(true) // 1
Number(false) // 0
Number('123') // 123
Number('123abc') // NaN
string类型的强制类型转换
string类型的强制类型转换,使用String函数。
String(123) // '123'
String(true) // 'true'
String(undefined) // 'undefined'
boolean类型的强制类型转换
boolean类型的强制类型转换,使用Boolean函数。
Boolean(1) // true
Boolean(0) // false
Boolean('') // false
Boolean('hello') // true
它的转换规则相对简单:除了以下五个值的转换结果为false,其他的值全部为true。
undefined
null
0(包含-0和+0)
NaN
''(空字符串)
自动转换
遇到以下三种情况时,JavaScript 会自动转换数据类型,即转换是自动完成的,用户不可见。
第一种情况,不同类型的数据互相运算。
123 + 'abc' // "123abc"
第二种情况,对非布尔值类型的数据求布尔值。
if ('abc') {
console.log('hello')
} // "hello"
第三种情况,对非数值类型的值使用一元运算符(即+和-)。
+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
自动转换的规则是这样的:预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String()函数进行转换。如果该位置既可以是字符串,也可能是数值,那么默认转为数值。
由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean()、Number()和String()函数进行显式转换。