首先从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的操作大致为:

  1. input为原始值,直接返回;
  2. 不是原始值,调用该其的valueOf()方法,如果结果是原始值,返回原始值;
  3. 调用valueOf()不是原始值,调用此其的toString()方法,如果结果为原始值,返回原始值;
  4. 如果返回的不是原始值,抛出异常TypeError。

当preferredType传入String时,上述流程第2步和第3步调换顺序,即先执行toString。
以上时非原值转换成原值的相关方法,下面来讲讲JS发生隐式转换的一些场景。

宽松数值比较
即我们常用的>,<,==的情况,规则如下:

  1. 有非原值的情况下,先转换成原值
  2. 两者都为null或者undefined时,return true
  3. 两者中出现NaN时,return false
  4. 两者存在string,number,bollean且类型不一致时,先转换成number再比较

数学运算
即常用的+,-,*,/ 四则运算,规则如下:

  1. -,*,/在转换成原值后,一律转成number再计算
  2. +在作为单目运算符时,操作同第一条
  3. +在作为双目运算符时,先转换成原值,如果两者中有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 无转换

阿陆
1 声望0 粉丝