算术、位、关系、相等操作符
一元操作符
++、–、+、-1
2const f=1.1
f-- // 0.000000000000009 浮点舍入错误
位操作符
按内存中表示数值的位来操作数值。JS中的所有数值都以IEE754 64位格式存储,但位操作符并不直接操作64位的值。而是先将64位的值转换成32位的整数,然后执行操作,最后再将结果转换为64位。
在这个转换过程中,也会导致一个严重的负效应。对特殊的NaN和Infinity应用位操作时,这两个值会当做0来处理
有符号的整数,32位中前31位用于表示整数的值,第32位用于表示数值的符号(符号位)
- 正数以纯二进制格式存储
- 负数是以二进制补码存储(原码-反码-补码)
- 按位非NOT (波浪线~)
本质是操作数的负值-1
- 按位与AND(和好符号&)
- 按位或OR (竖线符号|)
- 按位异或XOR (插入符号^):不同为1,相同为0
- 左移(<<):将数值的所有为向左移动指定的位数
1 | const value= 2 // 等于二进制的10 |
向左移位后,原数值的右侧多出了5个空位,左移操作会以0来填充这些空位。左移操作不会影响操作数的符号位。
- 有符号的右移(》》):将数值向右移动,但保留符号位。有符号的右移与左移恰好相反
1 | const newValue= 64 //二进制的10 00000 |
有符号的右移在移动过程中也会出现空位,不过这次的空位出现在原数值的左侧、符号位的右侧。此时会用符号位的值来填充所有空位。
- 无符号右移(>>>):对正数来说无符号的右移和有符号的右移相同。但对于负数,无符号右移会将负数的二进制当成正数的二进制码。负数以其绝对值的二进制的补码形式表示,就会导致无符号右移的结果非常大
1 | const oldValue= -64 //二进制的 26个1 000000 |
布尔操作符
- 逻辑非会直接发生转换。
- 逻辑与和逻辑或可以应用于任何类型的操作数,在有一个操作数不是布尔值的情况下,逻辑与和逻辑非不一定返回布尔值。
- 逻辑非NOT(!)
逻辑非操作符首先会将他的操作数转换为一个布尔值,然后再对其取反
- 逻辑与AND(&&)
短路操作,如果第一个操作数是false,无论第二个惭怍书是什么值,结果都是false
第一个操作数如果转布尔值为false时,则返回第一个操作数(null、NaN、undefined、’’、0、-0)
- 逻辑或OR
短路操作,如果第一个操作数是true,无论第二个惭怍书是什么值,结果都是true
第一个操作数如果转布尔值为false时,则返回第而个操作数,如果两个操作数转而不都为false,则返回该操作数(null、NaN、undefined、’’、0、-0)
可以利用逻辑或来避免为变量赋null/undefined值
1 | const myObject= preferedObject || backupObject |
乘性操作符
在操作数不为数值的时候会执行自动的类型转换Number()
- 乘法*
- 有一个操作数是NaN,则返回NaN
- Infinity * 0 —— NaN
- Infinity * Infinity —— Infinity
- Infinity 与非0数值相乘,结果是Infinity或-Infinity,取决于有符号操作数的符号
- 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后再用上面的方法
- 除法/
- 有一个操作数是NaN,则返回NaN
- Infinity / Infinity —— NaN
- 0 / 0 —— NaN
- 如果非0的有限数被0除,则结果是Infinity/-Infinity,取决于有符号操作数的符号
- 如果是Infinity被任何非0数值除,则结果是Infinity/-Infinity,取决于有符号操作数的符号
- 如果有一个操作数不是数值,则在后台调用Number()
如果结果超过了JS数值的范围,则返回Infinity或-Infinity
- 求模(余数%)
- Infinity/ 有限大的数值——NaN
- Infinity/ Infinity—— NaN
- 有限大的数值/ 0——NaN
- 有限大的数值/ 无穷大的数值——结果是被除数
- x/0 —— 0
- 有一个数不是操作数时,会先调用Number()
加性操作符
- 加法+
- 一个操作数是NaN,则返回NaN
- Infinity+Infinity——Infinity
- -Infinity+(-Infinity)—— -Infinity
- Infinity + (-Infinity)—— NaN
- (+0) + (+0) —— +0
- (-0) + (-0) —— -0
- (+0) + (-0) —— +0
- 两个操作数都是字符串,则拼接
- 一个操作数是字符串,则将另一个操作数转换为字符串,然后再拼接
- 如果有一个操作数是对象、数值、布尔,则调用他们的toString得到相应的字符串,然后再按照上面的规则
- 减法-
- 一个操作数是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()
- 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较
- 任何操作数与NaN比较时,都是false(无论做哪种比较)
字符串比较对应字符的字符编码,大写字母的字符编码全部<小写字母的字符编码。如果要按照字母表的顺序比较字符串的大小,可以先把两个操作数转换为相同的大/小写格式,然后再比较。
1 | '23' < '3' // true |
相等操作符
1. 相等== 和不相等 !=
先转换再比较(强制转换)
- 如果有一个操作数是布尔时,则在比较相等性之前将其转换为数值,false-0、true-1
- 如果有一个操作数是字符串,另一个操作数是数值,先将字符串转换为数值
- 如果一个操作数是对象,另一个不是,则调用对象的valueOf,用得到的基本类型值按照上面的方法判断
- null和undefined相等
- 比较相等性之前,不能将null、undefined转换为其他任何值
- 有一个操作数是NaN,则相等返回false,不相等返回true(NaN和自身也不相等)
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true。否则false
2. 全等=== 和不全等 !==
仅比较而不转换
逗号操作符
可用于声明多个变量,还可以用于赋值。在用于赋值时,逗号操作符总会返回表达式的最后一项
1 | var num1=1, num2=2,num3=3 |
在JS中switch中的case可以是常量、变量、表达式。switch语句在比较值的时候用的是全等操作符,因此不会发生类型转换。1
2
3
4
5switch(){
case value:
break;
default:
}
注意没有break时,就会执行完当前的case后,继续执行下一个。最后defalt用于在表达式不匹配前面任何一种case情况的时候。1
'a' + + 'b' // -> "aNaN"