An old dog learns code

JS中的隐式转换

September 21, 2018


隐式转换相当于调用Boolean(value)方法,其底层实现为ToBoolean(value)方法,转换规则如下表:

数据类型 转换为true的值 转换为false的值
Boolean true false
String 非空字符串
(value.length>0)
空字符串''
(value.length===0)
Number 非零值 0 或 NaN
Undefined \ false
Null \ false
Symbol 任何值 \

注:转换为Boolean为false的值有:'', false, 0, NaN, undefined, null

例1

Boolean('') //空字符串,0
Boolean(' ') //含有一个空格的字符串,1



基本类型转换为String类型

隐式转换相当于调用String(value)方法,其底层实现为ToString(value)方法,规则如下表:

数据类型 转换为string的值
Boolean true=>'true'
false=>'false'
Null 'null'
Undefined 'undefined'
Number 数字的string值
String 不转换
Symbol 抛出TypeError异常

例2

String(false) //'false'
String(1.32e3) //'1320'
String(-Infinity) //'-Infinity'
String(NaN) // 'NaN'



基本类型转换为Number类型

隐式转换相当于调用Number(value)方法,底层实现为ToNumber(value)方法,规则如下表:

数据类型 转换为number的值
Undefined NaN
Null 0
Boolean true=> 1
false=>0
Number 不转换
String 1.空字符串或仅有空格的字符串=>0
2.整数=>保留符号,忽略整数中的先导0,返回整数
3.浮点数=>保留符号,忽略先导0,返回浮点数
4.十六进制数=>返回相同大小的十进制数
5.二进制数=>返回相同大小的十进制数
6.八进制数=>返回相同大小的十进制数
7.科学记数法=>返回相同大小的十进制数
8.其他=>返回NaN
注:数字字符串中头尾2端的空白,转换时都将被忽略
Symbol 抛出TypeError异常

例3

Number('') //0
Number('    ') //0
Number(' -1.33e3 ') //-1330
Number(' 0x10') //16
Number(' 1232 4345') //NaN




对象隐式转换为基本类型

对象转换为基本类型时:

  1. 首先调用ToPrimitive ( input [, PreferredType] )方法,当input可转换为多种基本类型时,可选参数PrefreredType指定优先转换类型
  2. 随后调用OrdinaryToPrimitive(input,hint)方法,其中hint值由PrefreredType决定,且为以下之一:["default", "string", "number"]:

    1. 如果PrefreredType值为hint String, 则 hint值为"string",依次调用对象的toString, valueOf方法,直至返回值为基本类型
    2. 如果PrefreredType值为hint Number, 则 hint值为"number",依次调用对象的valueOf, toString方法,直至返回值为基本类型
    3. 如果PrefreredType未指定, 则 hint值为"default",按2步骤执行
    4. 如果上述执行完毕后,返回值仍不是基本类型,抛出TypeError异常

      注:
      1.Date对象在转换时,其PrefreredTypehint String
      2.以上对象默认转换规则,如果对象重写了默认的toString 和/或 valueOf方法,致使无法返回基本类型,那么将抛出TypeError异常

例4

let a = {};
a+1 //'[object Object]1'
a.toString() //'[object Object]'

function Test(){
    this.valueOf = function(){return 112233}
}
a = new Test();
a+1 //112234
String(a) //'[object Object]'

function Test2(){
  this.toString = function(){return []};
}
a= new Test2();
a+1 //TypeError: Cannot convert object to primitive value 
  • 上例中,先将a声明为空对象,a+1进行计算时,a按照规则2.3进行转换,先根据原型链调用Object.valueOf()方法,返回对象自身,然后继续调用Object.toString()方法返回值'[object Object]',最后将a和数字1进行字符串拼接,得到结果;
  • 之后将a声明为Test类的实例对象,Test中重写了valueOf()方法,再次进行a+1计算时,按照规则2.3进行转换,此时valueOf()方法返回值为基本类型,不再继续调用toString()方法,于是结果变为112234;而调用String(a)将对象优先转换为string类型,仍然调用的是Object.toString()方法,结果与之前相同
  • 再次声明Test2类,确保其2个方法都没有返回基本类型,再次计算实例a+1时,抛出了TypeError错误