首先从JS的基本类型说起,如很多人所知,JS算上ES6新增的symbol,总共有七大基础类型:null,undefined,boolean,number,string,symbol和object。
而在其中,还有一个叫原值的概念,当非原值的类型参与一些数学运算或者比较的时候,通常会先转换成原值再进行操作。
- 原值:null,undefined,boolean,number,string,symbol
- 非原值:object
非原值转换为原值会调用一个名为toPrimitive的方法(es6中似乎将该方法放到了symbol的原型中,即Symbol.toPrimitive)。调用方式为toPrimitive(input, preferredType)
其中input为输入的非原值,而preferredType表示希望转换的值(非必须传入),有Number和String(如果没有传preferredType,默认Date类型转String,其他类型转Number)。
当preferredType传入Number时,toPrimitive的操作大致为:
- input为原始值,直接返回;
- 不是原始值,调用该其的valueOf()方法,如果结果是原始值,返回原始值;
- 调用valueOf()不是原始值,调用此其的toString()方法,如果结果为原始值,返回原始值;
- 如果返回的不是原始值,抛出异常TypeError。
当preferredType传入String时,上述流程第2步和第3步调换顺序,即先执行toString。
以上时非原值转换成原值的相关方法,下面来讲讲JS发生隐式转换的一些场景。
宽松数值比较
即我们常用的>,<,==的情况,规则如下:
- 有非原值的情况下,先转换成原值
- 两者都为null或者undefined时,return true
- 两者中出现NaN时,return false
- 两者存在string,number,bollean且类型不一致时,先转换成number再比较
数学运算
即常用的+,-,*,/ 四则运算,规则如下:
- -,*,/在转换成原值后,一律转成number再计算
- +在作为单目运算符时,操作同第一条
- +在作为双目运算符时,先转换成原值,如果两者中有string,则都转换为string,返回string相加的结果,否则都转换为number,返回number相加后的结果。
注:{} + []
在本例中,由于JS的特性,如果{}既可以被认为是代码块,又可以被认为是对象字面量,那么JS会把他当做代码块来看待,即此处的式子会被转化成 + [] ,最终得到0。
附:
原值转换
值 | toNumber | toString | toBoolean |
---|---|---|---|
NaN | NaN | "NaN" | false |
Infinity | Infinity | "Infinity" | true |
[] | 0 | "" | true |
[1] | 1 | "1" | true |
null | 0 | "null" | false |
undefined | NaN | "undefined" | false |
{} | NaN | "[object Object]" | true |
function(){} | NaN | "function" | true |
Number()
arg | val |
---|---|
undefined | NaN |
null | +0 |
bollean | true为1,false为0 |
number | 无转换 |
string | 纯数字字符串可转换为对应数字,否则转换为NaN |
toString()
arg | val |
---|---|
undefined | "undefined" |
null | "null" |
bollean | "true"或"false" |
number | 对应的纯数字字符串 |
string | 无转换 |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。