前言
在第一篇文章中,讲解了 关于“==”时,JS做的类型转换。从第一篇文章中可以发现 == 时,基本类型都朝着数字类型转换,还是贴出上篇文章的图:
那么JS类型转换都是按照这个模式进行转换的吗?例如null能转换成数字类型吗?如果能,会转换成多少?
const data = 1 + null;
data;// 1
你想到这个结果了吗?
正文
基本类型转换
下面是JS类型转换的图表:
图表显示null转换成了0。不是说 null
没有 toString
和 valueOf
的方法的吗?怎么能转换成数字呢??
这完全不符合第一篇 == 的套路啊!
具体怎么回事呢?
问题在于JS类型转换只存在于“==”的时候吗?肯定不是!
除了==符号会产生类型转换,'+' '-' '*' '/' '>''<'等符号也会使JS发生类型转换,所以==的类型转换规则不是万能的,只适用于== 。那么应该如何记住类型转换这张表格呢?其实大部分转换规则是可以根据第一篇文章讲的==的转换规则得出正确答案的,只是有几个特殊的例子罢了。
第一篇文章讲到了 {}
会转换成字符串 [object Object]
,则:
比较特殊的就是undefined null类型:
- 在进行 == 的时候,undefined null 会尝试转换成基本类型,但是不存在
toString
valueOf
方法,所以无论如何是转换不成基本类型的。 - 在做字符串拼接的时候会按照表里面的转换成字符串的规则
- 在做数值运算的时候会按照表中转换成数字的规则
表格中 {}
转换成字符串类型和数值类型通常如下:
String({})// [object Object]
Number({})// NaN
Object类型转换成基本类型
ECMAScript内部有一个函数 ToPrimitive()
(这个函数不能在javascript中调用), 下面是转换规则:
ToPrimitive(input, PreferredType?)
这个可选的 PreferredType
表示最终要转换成的基本类型:
它是数字类型或者字符串类型,这取决于ToPrimitive()的结果是否可以转换成一个数字还是一个字符串。
如果PreferredType 是数字类型, 转换将遵循以下步骤:
- 如果输入的是基本类型,就直接返回它
- 如果输入的是
Object
(1)会先调用input.valueOf()
。如果结果是基本类型就返回它
(2)如果input.valueOf()
不是基本类型,就会调用input.toString()
,如果结果是基本类型就返回它
(3)如果还不能得到基本类型,就会抛出TypeError错误
如果PreferredType 是 String
, 第二条的(1)(2)顺序反转一下。
下面看一组转换情况:
Number([9]);// 指定转换方式 ->9
0 + [9];// 默认转换方式->'09'
(4) 如果指定了要转换的类型,则会优先调用转换的方法,例如:
var s = { toString: function () { return '7'; } };
String(s);// toString() => '7'
Number(s);// valueOf() => 7
Number() 与 parseInt()/parseFloat()
1.Number(num) 会对boolean string null 类型做一些转换:
parseFloat(true); // same as parseFloat('true') => NaN
Number(true); // 1
parseFloat(null); // same as parseFloat('null') => NaN
Number(null); // 0
parseFloat(''); // NaN
Number(''); // 0
也就是说Number走的是类型转换那张表。
我们经常使用 +[number]的形式来实现Number(number)。
2.parseInt(num,radix)/parseFloat(num,radix)可以设置解析的进制radix,并且会解析出合法的部分:
parseFloat('123.45#'); // 123.45
Number('123.45#'); // NaN
parseFloat('\t\v\r12.34\n');
parseInt()/parseFloat()才是真正的解析数字。
3.使用parseInt()去解析数字会有问题
Don’t use parseInt() to convert a number to an integer:coercion to string is an unnecessary detour and even then, the result is not always correct.(《SpeakingJavascript》)
情况一:整数>=21bit之后会用e表示数字大小
parseInt(1000000000000000000000.5, 10); // 1
首先转换成字符串:
String(1000000000000000000000.5); // '1e+21'
情况二:小数部分>=7bit会用e表示数字大小
parseInt(0.0000008, 10); // 8
String(0.0000008); // '8e-7'
总结:
1.大多情况下优先使用Number()
2.如果确定是解析字符串,并且取里面能提取出的数字,这种情况下使用parseInt()/parseFloat()
3.非十进制解析的情况下使用parseInt()/parseFloat()
后记
在做== 运算时:右侧世界undefined null ,永远不等于左侧的世界中的值,是因为undefined null 想转换成基本类型(和引用类型处理方式一致),但是它们没有toString valueOf方法。
这一篇undefined null 类型转换还可以看出:例如 + 运算,JS会根据实现,按照表格中的JS类型转换,{}转换成字符串[object Object],null转换成数字0,数组转字符串类似调用join。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。