算数运算符
number 运算
加减乘除
除法会直接得到小数
余数 x % 7
变态情况,-1 % 7 === -1
,不同于我们以往的认知,是因为JS直接把负号提取出来,1 % 7
是1,所以再加上负号,即为-1。数学中这种算法是不存在的,但是也能想象到-1 % 7
就相当于6 % 7
,余数应该为6。
指数 x ** 3
自增自减 x++ / ++x / x– / –x
a++
取a在前的值,++a
取a在后的值。(a的值都为2,只是这两个自增结果不同)
var a = 10 b = a++ 复制代码
答案为
b = 10
,a++
取前面的值,这里a++ = 10
,a = 11
。
a--
取a在前的值,--a
取a在后的值。(a的值都为4,只是这两个自减结果不同)
求值运算符 +x
只是求值
负数运算符 -x
不同于求值运算符,负数运算符会将值的符号进行正负颠倒
string 运算
字符串只支持加法运算
下面这些运算虽然是错误的,但JS仍能给出“结果”。
比较运算符
>
大于
<
小于
>=
大于等于
<=
小于等于
==
JS三位一体图
虽然 0 == []
、0 == '0'
、0 == '\t'
,但是右边三个互不相等。
不要使用==
,用===
代替。==
的问题在于,它总是自作聪明(自动类型转换)。
x == y真值表
令人难以理解,[] == false
但不是falsy
,[] == false
但{}
却不是,[[]] == false
。
x === y真值表
没有任何费解。基本类型看值是否相等,对象看地址是否相等。
[] !== []
{} !== []
特例NaN !== NaN
!=
===
!==
布尔运算符
或且非
||
或
&&
且
!
非
短路逻辑
console && console.log && console.log('hi')
防御性编程,以防console不存在而报错。
a = a || 100
a的保底值,a存在则为a,不存在就为100。但其实存在漏洞,因为五个falsy值都可以让a为假。
使用下面代码可以避免这个问题:
二进制位运算符
或、与、否
|
两个位都为0,则结果为0,否则为1
上面得不到正确结果是因为没有转化为二进制
&
两个位都为1,则结果为1,否则为0
~
对一个二进制位取反(0
变为1
,1
变为0
)
~3 // -4
复制代码
上面表达式对3
进行二进制否运算,得到-4
。之所以会有这样的结果,是因为位运算时,JavaScript 内部将所有的运算子都转为32位的二进制整数再进行运算。
3
的32位整数形式是00000000000000000000000000000011
,二进制否运算以后得到11111111111111111111111111111100
。由于第一位(符号位)是1,所以这个数是一个负数。JavaScript 内部采用补码形式表示负数,即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值。这个数减去1等于11111111111111111111111111111011
,再取一次反得到00000000000000000000000000000100
,再加上负号就是-4
。考虑到这样的过程比较麻烦,可以简单记忆成,一个数与自身的取反值相加,等于-1。
异或
^
两个位相同,则结果为0,否则为1
左移右移
<<
和>>
现在有多个1,往右移会被吃掉,所以结果还是0b0001
。往左移会补全。
头部补零的右移运算符
>>>
头部补零的右移运算符(>>>
)与右移运算符(>>
)只有一个差别,就是一个数的二进制形式向右移动时,头部一律补零,而不考虑符号位。所以,该运算总是得到正值。对于正数,该运算的结果与右移运算符(>>
)完全一致,区别主要在于负数。
4 >>> 1
// 2
-4 >>> 1
// 2147483646
/*
* 因为-4的二进制形式为11111111111111111111111111111100,
* 带符号位的右移一位,得到01111111111111111111111111111110,
* 即为十进制的2147483646。
*/
复制代码
这个运算实际上将一个值转为32位无符号整数。
查看一个负整数在计算机内部的储存形式,最快的方法就是使用这个运算符。
-1 >>> 0 // 4294967295
复制代码
上面代码表示,-1
作为32位整数时,内部的储存形式使用无符号整数格式解读,值为 4294967295(即(2^32)-1
,等于11111111111111111111111111111111
)。
一些妙用
使用与运算符判断奇偶
偶数 & 1 = 0
奇数 & 1 = 1
复制代码
使用~,>>,<<,>>>,|来取整
console.log(~~ 6.83) //6
console.log(6.93 >> 0) //6
console.log(6.83 << 0) //6
console.log(6.83 | 0) //6
console.log(6.83 >>> 0) //6
复制代码
使用^
交换a b的值
var a = 5
var b = 8
a ^= b // a = a ^ b的简写
b ^= a
a ^= b
console.log(a) //8
console.log(b) //5
复制代码
其他运算符
点运算符
语法
对象.属性名 = 属性值 //只能用到对象上
复制代码
作用
读取对象的属性值
疑问
不是对象,为什么也可以有属性?
'a-b-c'.split('-')
复制代码
JS有特殊逻辑,点前面不是对象,就把它封装成对象
number 会变成 Number对象
string 会变成 String对象
bool 会变成 Boolean对象
例:当a这个数字使用点运算符时
在调用toString时,JS首先将a变成一个拥有方法的对象,封装对象a1。
得到封装对象a1的toString。
干掉封装对象a1。
void运算符
语法
void 表达式或语句
复制代码
作用
求表达式的值,或执行语句
然后void的值总是为undefined
需求
<a href="http://example.com" onclick="f();return false;">点击</a>
return假值可以组织默认动作
<a href="">文字</a>
改用void可以炫技。
逗号运算符
语法
表达式1,表达式2,...,表达式n
复制代码
作用
将表达式n的值作为整体的值
使用
let a = (1,2,3,4,5)
那么a的值就是5。
let f = (x) = (console.log('平方值为'),x * x)
注意括号不能省略。
运算符优先级
优先级是什么
不同运算符
1 + 2 * 3 //返回7
//先乘除,后加减
复制代码
相同运算符
从左到右 a + b + c
从右到左 a = b = c = d
优先级就是先算什么后算什么
注意:圆括号优先级最高!