类型转换
JavaScript中的取值类型非常灵活,如当JavaScript期望使用一个布尔值的时候,你可以提供其它数据类型的,JavaScript将根据需要自行转换数据类型。如下示例:
10 + “objects” // 结果“10objects”,数字10被转换成字符串
“7” * “4” // 结果是28,两个字符串被转换成了数字。
var n = 1 - "x" // 结果是n等于NaN,因为字符串“x”无法被转换为数字
n + "objects" // 结果是“NaN objects”。NaN被转换成了字符串类型
值 | 字符串 | 数字 | 布尔值 | 对象 |
undefined | "undefined" | NaN | false | throws TypeError |
null | "null" | 0 | false | throws TypeError |
true | "true" | 1 | true | new Boolean(true) |
false | "false" | 0 | false | new Boolean(false) |
""(空字符串) | "" | 0 | false | new String("") |
"1.2" | "1.2" | 1.2 | true | new String("1.2") |
"one" | "one" | NaN | true | new String("one") |
0 | "0" | 0 | false | new Number(0) |
-0 | "0" | -0 | false | new Number(-0) |
NaN | "NaN" | NaN | false | new Number(NaN) |
Infinity | "Infinity" | Infinity | true | new Number(Infinity) |
-Infinity | "-Infinity" | -Infinity | true | new Number(-Infinity) |
1 | "1" | 1 | true | new Number(1) |
{} | "[object Object]" | NaN | true | new object({}) |
[] | "" | 0 | true | new object([]) |
[9] | "9" | 9 | true | new object([9]) |
["a"] | "a" | NaN | true | new object(["a"]) |
function(){} | "函数的实现代码" | NaN | true |
小结:字符串转换成数字,如果字符串的开始和结尾有空格的数字可以正常转换成数字,如“ 123 ”可以转换成数字123,但如果有其它特殊符号得到的数字结果将是NaN。
显示类型转换
尽管JavaScript可以自动做许多类型转换,但有时为了使代码变得清晰易读需要使用显示类型转换。
做显示类型转换最简单的方法就是使用Boolean(),Number(),String(),object()函数,当前面没有关键字new时,它们会作为类型转换函数,来将值转换成我们需要的数据类型。需要注意的是,除了null和undefined之外的任何值都具有toString()方法,这个方法的执行结果通常和String方法的返回结果一致,同样需要注意的是,如果试图把null或undefined转换为对象,会抛出一个类型错误的错误。object()函数在这种情况下不会抛出异常,它仅简单的返回一个新创建空间的对象。
在计算机程序中数字的解析和格式化是非常普通的工作,JavaScript中提供了专门的函数和方法来做更加精确的数字到字符串,字符串到数字的转换。
Number类定义的toString()方法可以接收表示转换基数(进制)的可选参数,如果不指定此参数,转换规则将是基于十进制。同样也可以将数字转换成其它进制。
如下示例:
var num = 10;
binay_str = n.toString(2); // 将数字转换成二进制
octal_str = n.toString(8); // 将数字转换成八进制
hex_str = n.toString(16); // 将数字转换成十六进制
当处理财务或科学数据的时候,对于输出小数点位置和有效数字位数,或者是科学技术法时,Number类为这种小数到字符串的转换提供了三个方法:
toFixed(位数):根据参数指点小数点后的位数,如果有效位后面还有小数,则按四舍五入的方式进位。
toExponential(有效位):科学计数法,小数点前只保留1位,根据参数指定小数点后的有效位,同样如果有效位后面还有小数按四舍五入进位。
torecision(有效位):根据指定的有效数字位数将数字转换成字符串,如果有效位数字少于数字整数部分的位数,则转换成科学计数法。
如下示例:
var n = 123456.789;
n.toFixed(0); // "123457"四舍五入进1
n.toFixed(2); // "123456.79""四舍五入进1
n.toFixed(5); // "123456.78900"位数不足用0补位
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”“0X”,parseInt()将其解释为十六进制,parseInt()和parseFloat()都会跳过任意数量的前导空格,尽可能解析更多数值字符串,并忽略后面的内容,如果第一个非空格字符是非法的特殊符号,将返回NaN。
如下示例:
parseInt("3 Hello World"); // 结果是3
parseFloat(" 3.14 Hello World"); // 结果是3.14
parseInt("-12.34"); // 结果是-12
parseInt("oxFF"); // 结果是255
parseInt("0xff"); // 结果是255
parseInt("-0xff"); // 结果是-255
parseFloat(".1"); // 结果是0.1
parseInt("0.1"); // 结果是0
parseInt(".1"); // 结果是NaN
parseFloat("#23.33"); // 结果是NaN
parseInt()可以接收第二个可选参数,这个参数指定数字转换的基数,取值范围是2-36。
如下示例:
parseInt("11",2) // 将二进制转换成十进制输出
parseInt("ff",16); // 将十六进制转换成十进制输出
parseInt("zz",36); // 将三十六进制转换成十进制输出
parseInt("077",8); // 将八进制转换成十进制输出
对象转换为原始值
对象到布尔值转换非常简单,所有对象(包括数组,函数)都转换为true,对于对象到字符串和对象到数字的转换是通过调用待转换对象的一个方法来完成的。
所有对象继承了两个转换方法,一个是toString()它的作用是返回一个反应这个对象的字符串,很多类定义了更多特定版本的toSring()方法,如数组类的toString()方法将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。函数类的toString()返回这个函数的实现定义的表示方式。日期类Date定义的toString()返回一个可读的日期和时间字符串。RegExp类定义的toString()将RegExp对象转换为正则表达式字符串。
[1,2,3].toString(); // 结果是"1,2,3"
(function(x) {...}).toString(); // 结果是"function(x) {...}"
/\d+/g.toString(); // 结果是"/\\d+/g"
new Date().toString(); // 当前时间
另一个转换对象的函数是valueOf(),如果存在原始值,它就默认将对象转换为表示它的原始值,对象是复合值,而且大多数对象无法真正表示为一个原始值,因此valueOf()方法简单的返回对象本身,而不是返回一个原始值。
如下示例:
var d = new Date();
d.valueOf(); // 打印当前时间的时间戳1553439997486
var a = [1,2,3];
a.valueOf(); // 打印[1,2,3]
JavaScript中对象到字符串的转换经历如下步骤:
1、如果对象具有toString()方法,则调用这个方法,如果它返回一个原始值,JavaScript将整个值转换成字符串(如果本身是字符串的话),并返回这个字符串结果。
2、如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么JavaScript会调用valueOf()方法,如果返回值是原始值,JavaScript将整个值转换为字符串并返回这个字符串结果。
3、如果JavaScript无法从toString()或valueOf()获得一个原始值,此时它将抛出一个类型错误的异常。
对象到数字的转过程也是一样,只是它首先会调用valueOf()。
1、如果对象有valueOf()方法,后者返回一个原始值,则JavaScript将这个原始值转换为数字并返回这个数字。
2、如果没有valueOf()这个方法,调用toString()方法,后者返回一个原始值,则JavaScript将其转换成字符串后返回。
3、如果没有valueOf()和toSring()方法,抛出一个类型错误异常。
对象转换为数字的细节解释了为什么空数组会被转换为数字0以及为什么具有单个元素的数组同样会转换成一个数字。数组继承默认的valueOf方法,这个方法返回一个对象而不是一个原始值,因此,数组到数字的转换调用toString方法,空数组转换成空字符串,空字符串转换成数字0,含有一个元素的数组转换为字符串的结果和这个元素转换字符串的结果一样。如果数组只包含一个数字元素,这个数字转换为字符串,在转换回数字。
"+" 和 "==" 应用的对象到原始值的转换包含日期对象的一种特殊情形。 日期类是JavaScript语言核心中唯一的预先定义类型,它定义了有意义的向字符串和数字类型的转换。 对于所有非日期的对象来说, 对象到原始值的转换基本上是对象到数字的转换(首先调用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