*空单元格表示不必要也没有执行转换
值 | 转换为 | |||
---|---|---|---|---|
字符串 | 数字 | 布尔值 | 对象 | |
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] (1个数字元素数组) | “9” | 9 | true | |
[‘a’] (其它元素数组) | 使用join()方法 | NaN | true | |
function(){} (任意函数) | 比较复杂,参考下方 | NaN | true |
转换和相等性
由于JavaScript可以做灵活的类型转换,因此其‘==’相等运算符也随相等的含义灵活多变。例如,如下这些比较结果均是true:
null == undefined //这两个值被认为相等
"0" == 0 //在比较之前字符串转换成数字
0 == false //在比较前布尔值转换成数字
"0" ==false //在比较前字符串和布尔值都转换成数字
需要特别注意的是,一个值还换为另一个值并不意味着两个值相等。比如,如果在期望使用布尔值的地方使用了undefined,它将会转换为false,但这并不表明undefined==false。JavaScript运算符和语句期望使用多样化的数据类型,并可以相互转换。if语句将undefined转换为false,但‘==’运算符从不试图将其操作数转换为布尔值。
显式类型转换
做显式类型转换最简单的方法就是使用Boolean()、String()或Object()函数。当不通过new运算符调用这些函数时,它们会作为类型转换函数并按照上述表中所描述的规则做类型转换:
Number('3') //=>3
String(false) //=>'false'或使用false.toString()
Boolean([]) //=>true
Object(3) //=>new Number(3)
需要注意的是,除了null和undefined之外的任何值都具有toString()方法,这个方法执行结果通常和String()方法的返回结果一致。同样需要注意的是,如果试图把null或undefined转换为对象,则会抛出一个类型错误(TypeError)。Object()函数在这种情况下不会抛出异常:它仅简单的返回一个新创建的空对象。
JavaStript中的某些运算符会做隐式的类型转换,有时用于类型转换。
x+"" //等价于String(x)
+x //等价于Number(x),也可以写成 x-0
!!x //等价于Boolean(x),注意是双叹号
在计算机程序中数字的解析和格式化是非常普通的工作,JavaScript中提供了专门的函数和方法用来做更加精确的数字到字符串和字符串到数字的转换。
Number类定义的toString()方法可以接收表示转换基数的可选参数,如果不指定此参数,转换规则将是基于十进制。同样,亦可以将数字转换为其他进制数(范围在2-36之间),例如:
var n=17;
binary_string=n.toString(2);//转换为‘10001’
octal_string="0"+n.toString(8);//转换为‘021’
hex_string="0x"+n.toString(16);//转换为‘0x11’
当处理财务或科学数据的时候,在做数字到字符串的转换过程中,你期望自己控制输出小数点位置和有效数字位数,或者决定是否需要指数记数法。
Number类为这种数字到字符串的类型转换场景定义了三个方法。
toFixed():根据小数点后的指定位数将数字转换为字符串,它从不使用指数记数法。
toExponential():使用指数记数法将数字转换为指数形式的字符串,其中小数点前只有一位,小数点后的位数则由参数指定。
toPrecision():根据指定的有效数字位数将数字转换成字符串。如果有效数字的位数少于数字整数部分的位数,则转换成指数形式。
三个方法都会适当的进行四舍五入或填充0.
var n=123456.789;
n.toFixed(0);//=>'123457'
n.toFixed(2);//=>'123456.79'
n.toFixed(5);//=>'123456.78900'
n.toExponential(1);//=>'1.2e+5'
n.toExponential(3);//=>'1.235e+5'
n.toPrecision(4);//=>'1.235e+5'
n.toPrecision(7);//=>'123456.8'
n.toPrecision(10);//=>'123456.7890'
字符串转换成数字:
如果通过Number()转换函数传入一个字符串,它会试图将其转换为一个整数或浮点数直接量,这个方法只能基于十进制数进行转换,并且不能出现非法的尾随字符。
parseInt()函数和parseFloat()函数(它们是全局函数,不从属于任何类的方法)更加灵活。parseInt()只解析整数,而parseFloat()则可以解析整数和浮点数。如果字符串前缀是‘0x’,parseInt()将其解释为十六进制数,parseInt()和parseFloat()都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回NaN:
parseInt('3 blind mice');//=>3
parseFloat('3.14 meters');//=>3.14
parseInt('-12.34');//=>-12
parseInt('0xff');//=>255
parseInt('-0xff');//=>-255
parseFloat('.1');//=>0.1
parseInt('0.1');//=>0
parseInt('.1');//=>NaN:整数不能以‘.’开始
parseFloat('$72.47');//=>NaN:数字不能以‘$’开始
parseInt()可以接收第二个可选参数,这个参数指定数字转换的基数,合法的取值范围是2-36,例如:
parseInt('11',2);//=>3(1*2+1)
parseInt('ff',16);//=>255(15*16+15)
parseInt('zz',36);//=>1295(35*36+35)
parseInt('077',8);//=>63(7*8+7)
parseInt('077',10);//=>77(7*10+7)
对象转换为原始值
对象到布尔值的转换非常简单:所有的对象(包括数组和函数)都转换为true。对于包装对象亦是如此:new Boolean(false)是一个对象而不是原始值,它将转换为true。
对象到字符串和对象到数字的转换是通过调用待转换对象的一个方法来完成的。一个麻烦的事实是,JavaScript对象有两个不同的方法来执行转换,值得注意的是,这里提到的字符串和数字的转换规则只适用于本地对象。宿主对象(例如,由Web浏览器定义的对象)根据各自的算法 可以转换成字符串和数字。
所有的对象继承了两个转换方法。
第一个是toString(),它的作用是返回一个反映这个对象的字符串。默认的toString()方法返回:
({x:1,y:2}).toString();//=>'[object Object]'
很多类定义了更多版本的toString()方法。例如,数组类的toString()方法将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。函数类的toString()方法返回这个函数的实现定义的表示方式。实际上,这里的实现方式是通常是将用户定义的函数转换成JavaScript源代码字符串。日期类定义的toString()返回了一个可读的日期和时间字符串。RegExp类定义的toString()方法将RegExp对象转换为表示正则表达式直接量的字符串:
[1,2,3].toString();//=>'1,2,3'
(function(x){f(x);}).toString();//=>'function(x){f(x);}'
/\d+/g.toString();//=>'/\d+/g'
new Date(2010,0,1).toString();//=>'Fri Jan 01 2010 00:00:00 GMT-0800 (PST)'
另一个转换对象的函数是valueOf()。这个方法的任务并未详细定义:如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的valueOf()方法简单的返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单的继承了这个默认方法,调用这些类型的实例的valueOf()方法只是简单返回对象本身。日期类定义的valueOf()方法会返回它的一个内部表示:1970年1月1日以来的毫秒数。
var d=new Date(2010,0,1);//=>2010年1月1日(太平洋时间)
d.valueOf();//=>1262332800000
通过使用toString()和valueOf()方法,就可以做到对象到字符串和对象到数字的转换了。但需要注意的是,在某些特殊的场景中,JavaScript执行了完全不同的对象到原始值的转换。
JavaScript中对象到字符串的转换经过了如下几个步骤:
1:如果对象具有toString()方法,则调用这个方法。如果它返回一个原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。需要注意的是,原始值到字符串的转换在上表中已经有了详尽的说明。
2:如果对象没有toString()方法,或者这个方法并不返回原始值,那么JavaScript会调用valueOf()方法。如果存在这个方法,JavaScript调用它。如果返回值是原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
3:否则,JavaScript无法从toString()或valueOf()获得一个原始值,因此这是它将抛出一个类型错误异常
在对象到数字的转换过程中,JavaScript做了同样的事情,只是它会首先尝试使用valueOf()方法:
1:如果对象具有valueOf()方法,后者返回一个原始值,则JavaScript将这个原始值转换为数字(如果需要的话)并返回这个数字
2:否则,如果对象具有toString()方法,后者返回一个原始值,则JavaScript将其转换并返回。
3:否则,JavaScript抛出一个类型错误异常
对象转换为数字的细节揭示了为什么空数组会被转换为数字0以及为什么具有单个元素的数组同样会转换成一个数字。数组继承了默认的valueOf()方法,这个方法返回一个对象而不是一个原始值,因此,数组到数字的转换则调用toString()方法。空数组转换为空字符串,空字符串转换成数字0.含有一个元素的数组转换为字符串的结果和这个元素转换字符串的结果一样。如果数组只包含一个数字元素,这个数字转换为字符串,再转换回数字.
JavaScript中的‘+’运算符可以进行数学加法和字符串连接操作。如果它的其中一个操作数是对象,则JavaScript将使用特殊的方法将对象转换为原始值,而不是使用其他算术运算符的方法执行对象到数字的转换,‘==’相等运算符与此类似。如果将对象和一个原始值比较,则转换将会遵照对象到原始值的转换方式进行。
‘+’和‘==’应用的对象到原始值的转换包含日期对象的一种特殊情形。日期类是Javacript语言核心中唯一的预先定义类型,它定义了有意义的向字符串和数字类型的转换。对于所有非日期的对象来说,对象到原始值的转换基本上是对象到数字的转换(首先调用valueOf()),日期对象则使用对象到字符串的转换模式,然而,这里的转换和上文讲述的并不完全一致:通过valueOf()或toString()返回的原始值将被直接使用,而不会被强制转换为数字或字符串。
和‘==’一样,‘<’运算符以及其他关系运算符也会做对象到原始值的转换,但要出去日期对象的特殊情形:任何对象都会首先尝试调用valueOf(),然后调用toString()。不管得到的原始值是否直接使用,它都不会进一步被转换为数字或字符串。
‘+’、‘==’、‘!=’和关系运算符是唯一执行这种特殊的字符的字符串到原始值的转换方式的运算符。其他运算符到特定类型的转换都很明确,而且对日期对象来讲也没有特殊情况。例如‘-’运算符把它的两个操作数都转换为数字。下面的代码展示了日期对象和‘+’、‘==’、‘-’以及‘>’的运行结果:
var now=new Date();//创建一个日期对象
typeof(now+1);//=>'string':'+'将日期转换为字符串
typeof(now-1);//=>'number':'-'使用对象到数字的转换
now==now.toString();//=>true:隐式的和显式的字符串转换
now>(now-1);//=>true:'>'将日期转换为数字