-
前言
JavaScript是一种非常灵活的弱类型的语言,它的灵活性的一方面体现在其繁杂多样的类型转换。比如当JavaScript期望使用一个布尔值的时候(比如if语句中)你可以提供任一类型的值,JavaScript会按照需要自行转换类型;当使用==操作符比较两个类型值的时候,也会对两个操作数按需进行转换,同样的事情也发生在使用+,>和<等操作符时。这些灵活繁杂的转换往往会使初学者不知所措,本文对JavaScript的类型转换做一个总结。
-
JavaScript中的类型分类
JavaScript中的类型可以分为两大类:原始类型( primitive types)和对象类型(object types).其中原始类型包括数字number,字符串string,布尔boolean,null和undefined五种;除此五种之外的类型都是对象类型(包括function,array,regex等).
-
原始类型到其他类型的转换
JavaScript中对于不同类型值之间的转换见下表(该表为<JavaScript权威指南>第三章表3-2)
值 字符串 数字 布尔值 对象 undefined “undefined” NaN false throws TypeError null “null” 0 false throws TypeError true “true” 1 new Boolean(true) false “false” 0 new Boolean(false) “”(空字符串) 0 false new String(“”) “1.2” 1.2 true new String(“1.2”) “one” NaN true new String(“one”) 0 “0” false new Number(0) -0 “0” false new Number(-0) NaN “NaN” false new Number(NaN) Infinity “Infinity” true new Number(Infinity) -Infinity “-Infinity” true new Number(-Infinity) 1(其他非无穷大的数字) “1” true new Number(1) {} 待讨论 待讨论 true [] “” 0 true [9] “9” 9 true [‘a’] 使用join()方法连接各个元素,分隔符为逗号 NaN true function(){} 待讨论 NaN true 从上表可以看出,JavaScript中原始类型之间的类型转换已经被明确定义,原始类型到对象的转换也被明确定义,表格中有三个内容为"待讨论"的单元格,均是对象类型到原始类型之间的转换,是JavaScript类型转换的难点。这里简单对前两种情况做一下总结:
- 只有undefined,null,空字符串,0(包括0和-0)和NaN转换为布尔类型时会被转换为false,其余类型的值转换成布尔类型都是true
- 原始类型到对象类型的转换,null和undefined会抛出异常,而number,string和bool则会转换成对应的包装类型Number,String,Boolean.对于这三种原始类型,也可以使用Object构造函数转换成对象,Object构造函数会根据传入参数的具体值来调用Number,String或者Boolean中的一个来构造对象.代码如下
var num = new Number(10);
var str = new String("abc");
var boolean = new Boolean(false);
var num1 = new Object(10);
var str1 = new Object("abc");
var boolean1 = new Boolean(false);
console.log(typeof num + " " +num.constructor ); //输出object function Number() { [native code] }
console.log(typeof str + " " + str.constructor);//输出object function String() { [native code] }
console.log(typeof boolean + " " + boolean.constructor);//输出object function Boolean() { [native code] }
console.log(typeof num1 + " " + num1.constructor);//输出object function Number() { [native code] }
console.log(typeof str1 + " " + str1.constructor);//输出object function String() { [native code] }
console.log(typeof boolean1 + " " + boolean1.constructor);//输出object function Boolean() { [native code] }
对象类型到原始类型的转换
本小节中提到的"对象类型"仅指native objects,可以理解为由程序员定义的对象类型,不包括JavaScript宿主(比如浏览器)所定义的对象,因为宿主定义的对象可能有特殊的方法来进行类型转换.另外本小节标题里的原始类型仅包含bool,string和number三种类型,对象到null或者undefined的转换不需要讨论.而对象到bool类型的转换在上面已经讨论过,所有的对象类型转换布尔类型都是true,即使new Boolean(false)转换成布尔类型也是true.所以本小节值得讨论的内容就剩下对象类型到字符串的转换与对象类型到数字的转换.
对象到字符串和对象到数字类型的转换涉及到两个重要的方法,最终的转换结果会受到这两个方法返回结果的影响,这两个方法就是toString和valueOf.所有的对象都会从Object对象中继承到这两个方法.toString方法 用于返回对象的字符串表示(但是其实也可以不返回字符串).对于默认从Object继承而来的toString方法并不会返回太多有意义的内容.而valueOf方法目的是返回一个可以表示对象的原始类型值,但是由于对象的复杂性,大多数情况下根本不可能用一个原始类型值来表示,所以默认的valueOf只是返回对象自身.Date类型是一个特例,这是JavaScript预定义类型之中唯一重写了toString和valueOf方法的类型.
对象类型转换字符串类型步骤如下:
- 如果对象有toString方法,就调用toString方法,如果返回的是一个原始类型,把这个原始类型转换成字符串(当然如果toString返回的就是字符串就不需要了)
- 如果对象没有toString方法,或者toString返回的不是原始类型,就尝试调用valueOf方法,如果valueOf方法返回的是原始类型,则将原始类型转换成字符串(如果valueOf放回的就是字符串就不需要了)
- 如果toString方法和valueOf方法都不存在,或者他们的返回类型都不是原始类型,则抛出TypeError异常
对象类型转换数字类型步骤如下:
- 如果对象有valueOf方法并且该方法返回一个原始类型,则将这个原始类型转换成数字
- 否则如果对象有toString方法并且该方法返回原始类型,则将这个原始类型转换成数字
- 否则抛出TypeError异常
例子与对象转换字符串类似,不再给出.介绍到这里,大家应该知道为什么空数组转换成字符串是空字符串,但是转换成数字是0了吧.可以解释仅有一个元素的数组在转换成字符串和数字时的结果.