加法操作符(+)
转换规则:
-
如果两个数都是数值:
- 如果有**任一操作数**是
NaN,则返回NaN - 如果是
Infinity加-Infinity,则返回NaN.(若是一个操作数是Infinity/-Infinity.另一个数是有限或无限数(符号相同)都不影响Infinity/-Infinity)
- 如果有**任一操作数**是
-
如果有一个操作数是字符串:
- 如果两个操作数都是字符串,则将第二个字符串拼接到第一个字符串后面。
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串(String()),再将两个字符串拼接在一起。
- 如果操作数是布尔值,null,undefined:
- 则先在后台使用
Number()将其转换为数值。再执行前面的运算
- 则先在后台使用
- 如果操作数是对象:
- 有
valueOf()则调用valueOf()。如果发现valueOf()转换后的值不能参与运算,则执行下一步 - 调用
toString().再执行上面字符串的相关规则
- 有
举个栗子:
// 两个数都是数值
NaN + 5 // NaN
Infinity + -Infinity // NaN
Infinity - 20 // Infinity
-Infinity + 20 // -Infinity
// 有一个数是字符串
5 + '5' // '55'
true + '' // 'true'
'20' + '21' // '2021'
// 操作数是undefined,null,布尔值
true + false // 0
true + 9 // 10
undefined + 5 // NaN
// 操作数是对象
[] + null // 'null' (数组的valueOf()返回[]不能参与+运算,调用toString()<返回数组每一项转为
// 字符串后的数组>; []数组则为'',此时,相当于 '' + null.所以值为'null')
[] + {} // '[object Object]' ( 相当于 '' + {}, {}调用valueOf()方法结果为{},不能参与运算,再执行toString()<'[object Object]'>.此时相当于 '' + '[object Object]')
特殊情况:
表达式
{} + []的值为多少呢?[object Object] ?不是,值为
0。为什么?表达式中
{}会被当成独立的空代码块(不执行任何操作)/* 代码块可理解?0.0 */。最后+ []将[]显示强制转换为Number也就是0知道原因了,那么怎么解决呢?
使用
()包裹就行了。也就是({} + [])这样结果就是[object Object]了
补充:
let title, width; { title, width } = { title: 'menu', width: '80px' }
title,width结果是多少?答案是会报错!很奇怪?
现代javascript教程:结构赋值。这里有解释~
减法操作符(-)
转换规则
- 两个操作数是数值:
- 如果任一操作数是
NaN,则返回NaN。 - 对于
Infinity/-Infinity,同符号相减则为NaN.不同符号则不变(被减数)
- 如果任一操作数是
- **如果任一操作数是字符串、布尔值、null或undefined: **
- 先在后台使用
Number()将其转换为数值。再根据数值运算规则.
- 先在后台使用
- 如果任一操作数是对象:
- 调用其
valueOf()方法取得表示它的数值。再根据数值运算规则. - 如果没有
valueOf(),则调用toString()。再将得到的字符串转换为数值
- 调用其
举个栗子:
// 两个操作数都是数值
NaN - 5 // NaN
Infinity - Infinity // NaN
-Infinity - Infinity // -Infinity
// 任意操作数是....
5 - "" // 5
true - null // 1
5 - undefined // NaN
// 操作数是对象
[] - {} // NaN
[] - 5 // -5
关系操作符(>, <, <=, >=)
任何涉及
NaN的比较都会返回false
转换规则:
- 如果操作数是数值,则执行数值的比较。
- 如果操作数都是字符串,则逐个比较字符串中对应字符的编码。// 请看清楚...
- 如果任一操作数是数值,则将另一个操作数转换为数值,执行数值比较。
- 如果任一操作数是对象,则调用其
valueOf()方法。若是没有valueOf()则调用toString()方法。取得结果后在根据前面的规则执行比较。
举个栗子:
'23' < '3' // true 比较编码
'23' < 3 // false '23'会先转换为数值
'a' < 3 // false 'a'转换为数值为NaN
'a' >= 3 // false 同理
'Brick' < 'alphabet' // true 'a'的编码是97,‘B'的编码是66
[] < 3 // true []转换为0
[42] < ['43'] // true
['42'] < ['043'] // false 同为字符串则进行字符编码比较
特殊情况:
const a = { b: 42 } const b = { b: 43 } a < b // ? => false a == b // false a > b // ? => false a <= b // ? => true b <= a // ? => true我们需要记住的是:在
javascript中,<=我们不应该理解为"小于或等于"。实际上<=是“不大于”的意思。即a <= b处理为!(a > b)。>=同理
相等操作符( == )
转换规则:
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。
- 如果一个操作数是字符串,另一个操作数是数值。则尝试将字符串转换为数值,再比较是否相等。
- 如果一个操作数对象,且另一个操作数不是,则调用对象的
valueOf()方法取得其原始值,再根据前面的规则进行比较。
null == undefined
null和undefined**不会转换为其他类型 **
NaN不等于任何包括它自己在内的任何数,也就是说若是存在NaN操作数,则立即返回false.(NaN != NaN // true)
操作数都为对象,则比较是否指向同一块内存地址
举个栗子:
true == 1 // true
'55' == 55 // true
[] == "" // true
true == [] // false 首先 true会转换为1。[]调用valueOf()后不能执行运算,继而调用toString()转换为"",再将""转换为数值0
null == 0 // false 注意了:虽然null可以转换为0,但是在执行 == 操作时, null是不会进行转换的
[] == ![] // true
// 不理解?(小声bb: 真离谱...)首先会将右边的![]执行,值为false,
// 此时相当于[] == false。再应用第一条规则,即[] == 0,此时 []经过转换为“”, 再应用第二条规则,
// 即 0 == 0 所以为true
2 == [2] // true
// 还记得数组的toString么,若是数组存在多项则转换为以','分隔的字符串。相当于str.split(',')
// [2]被转换为'2',再转换为2
参考资料
- javascript高级程序设计(第四版)
- 你不知道的javascript(中)