对于JS这种语言来说,因为它是一种动态类型语言,变量是没有类型的,可以随时赋予任意值。
但是,数据本身和各种运算是有类型的,因此运算时变量需要转换类型。
大多数情况下,这种数据类型转换是自动的,但是有时也需要手动强制转换。
首先看下强制类型转换(显式)
之前提到的Namber、parseInt、parseFloat 都是强制类型转换;
这里在看阮一峰博客(http://javascript.ruanyifeng.com/grammar/conversion.html#toc1)
Number方法的转换,这里再做下记录:
(1)原始类型值的转换规则
数值:转换后还是原来的值。
字符串:如果可以被解析为数值,则转换为相应的数值,否则得到NaN。空字符串转为0。
布尔值:true转成1,false转成0。
undefined:转成NaN。
null:转成0。
(2)对象的转换规则
对象的转换规则比较复杂。
先调用对象自身的valueOf方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用Number方法,不再进行后续步骤。
如果valueOf方法返回复合类型的值,再调用对象自身的toString方法,如果toString方法返回原始类型的值,则对该值使用Number方法,不再进行后续步骤。
如果toString方法返回的是复合类型的值,则报错。
也提到了2种妙味课堂老师暂时没提到的方法:
String函数:强制转换成字符串
(1)原始类型值的转换规则
数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为“true”,false转为“false”。
undefined:转为“undefined”。
null:转为“null”
(2)对象的转换规则
如果要将对象转为字符串,则是采用以下步骤。
先调用toString方法,如果toString方法返回的是原始类型的值,则对该值使用String方法,不再进行以下步骤。
如果toString方法返回的是复合类型的值,再调用valueOf方法,如果valueOf方法返回的是原始类型的值,则对该值使用String方法,不再进行以下步骤。
如果valueOf方法返回的是复合类型的值,则报错。
// String方法的这种过程正好与Number方法相反
还有阮老师也提到了,布尔值转换
Boolean函数:强制转换成布尔值
(1)原始类型值的转换方法
以下六个值的转化结果为false,其他的值全部为true。
- undefined
- null
- -0
- +0
- NaN
- ''(空字符串)
(2)对象的转换规则
所有对象的布尔值都是true,甚至连false对应的布尔对象也是true。
Boolean(new Boolean(false)) // true
请注意,空对象{}和空数组[]也会被转成true。
Boolean([]) // true Boolean({}) // true
下面谈下隐式类型转换,或者说(js内部自动转换)
那么什么时候会发生隐式类型转换呢?
当遇到以下几种情况,JavaScript会自动转换数据类型:
-
不同类型的数据进行互相运算;
-
对非布尔值类型的数据求布尔值;
-
对非数值类型的数据使用一元运算符(即“+”和“-”)。
首先妙味老师提到的集中隐式类型转换情况:
隐式类型转换:
+ 200 + '3' 变成字符串
- * / % '200' - 3 变成数字
++ -- 变成数字
> < 数字的比较 、字符串的比较
! 取反 把右边的数据类型转成布尔值
==
// alert( Number('……') ); NaN
// alert( '……'-9 ); NaN
//NaN 数据类型转换失败的时候,会返回NaN;
// alert( '2' == 2 );
// alert('10'>9) 返回true, 此时是数字的比较
// alert( '10000000' > '9' ); 返回false,此时是字符串的比较,比较的是二者的编码;
// > < 是数字的比较与字符串的比较
// alert(!'ok'); 这时候返回false,为什么?
// 看了阮一峰的JS教程,我才明白,在预期为布尔值的地方,系统会自动调用内部的Boolean方法来转换
// Boolean方法 可以将任意类型的变量转为布尔值
另外需要一提的是 + 运算符,
有运算中存在a、 字符串的情况 // 两个运算子之中,只要有一个是字符串,则另一个不管是什么类型,都会被自动转为字符串,然后执行字符串连接运算
b、两个运算子都为数值或布尔值 // 这种情况下,执行加法运算,布尔值转为数值(true为1,false为0)
C、运算子之中存在对象
运算子之中存在对象(或者准确地说,存在非原始类型的值),则先调用该对象的valueOf方法。如果返回结果为原始类型的值,则运用上面两条规则;否则继续调用该对象的toString方法,对其返回值运用上面两条规则。 (这一块暂时还不理解,等学到object之后再仔细研究)
关于两个等号的数值转换:
详见司徒正美的博客:http://www.cnblogs.com/rubylouvre/p/3990290.html
另外为了避免这一问题的出现,大多数公司可能都要求,禁止使用双等号,直接使用三等号就好了
/*
这里说的隐性类型转换,是==引起的转换。
如果存在NaN,一律返回false
再看有没有布尔,有布尔就将布尔转换为数字
接着看有没有字符串, 有三种情况,对方是对象,对象使用toString进行转换;对方是数字,字符串转数字;对方是字符串,直接比较;其他返回false
如果是数字,对方是对象,对象取valueOf进行比较, 其他一律返回false
null, undefined不会进行类型转换, 但它们俩相等
这个顺序一定要死记,这是面试时经常问到的。
下面是一些杂题,自己做做
0 == undefined // false
1 == true // true
2 == {valueOf: function(){return 2}} // true
NaN == NaN // false
8 == undefined // false
1 == undefined // false
null == {toString: function(){return 2}} // false
0 == null // false
null == 1 // false
{ toString:function(){ return 1 } , valueOf:function(){ return [] }} == 1
*/
还有慕课老师PPT(帮助理解):
由于数据类型存在隐式转换,所以按照阮老师建议是:
由于自动转换有很大的不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean、Number和String方法进行显式转换
关于加、 减符号,慕课网《深入浅出javascript》当中也有提到
利用这种隐式转换的特性,如果我们想让那个一个变量的数据类型转换为数字,那么 num - 0 ; 此时这个num就是被隐式转换成了数字;
同理,想让一个变量的数据类型转换为字符串,那么 num + '' ; 变量加上一个空的字符串,此时num就被转换成了字符串
var num = 23; typeof(num + '') "string" var num = 'sg'; typeof(num-0) "number"
写在最后:
tips:通过对比妙味课堂的视频和网上的一些教程内容(个人博客,阮一峰,司徒正美等)发现都没有全部包含了数据类型转换的所有情况,所有在学习JS的时候,还需要自己多看,多动手,这样才更加准确和深刻理解。