這次帶給大家js隱式類型轉換使用步驟詳解,js隱式類型轉換使用的注意事項有哪些,下面就是實戰案例,一起來看一下。
相信剛開始了解js的時候,都會遇到 2 =='2',但 1 2 == 1 '2'為false的情況。這時候應該會是一臉懵逼的狀態,不得不感慨js弱類型的靈活讓人髮指,隱式類型轉換就是這麼猝不及防。結合實際的情況來看,有意或無意中涉及隱式類型轉換的情況還是很多的。既然要用到,就需要掌握其原理,知其然重要知其所以然更重要。
JavaScript 是弱型別語言,表示JavaScript 變數沒有預先決定的型別。
且變數的型別是其值的型別。也就是說變數目前的型別由其值決定,誇張點說上一秒種的string,下一秒可能就是個array了。另外當進行某些操作時,變數可以進行型別轉換,我們主動進行的就是顯式型別轉換,另一種就是隱式型別轉換了。例如:
var a = '1'; typeof a;//string a =parseInt(a); //显示转换为number typeof a //number a == '1' //true
弱類型的特性在帶給我們便利的同時,也會帶給我們困擾。趨利避害,充分利用這個特性的前提就是掌握類型轉換的原理,下面一起看一下。
老生常談的兩大類別資料型別:
原始型別
Undefined、 Null、 String、 Number、 Boolean
引用類型
object
此外還有一個es6新增的Symbol,先不討論它。對於這五類原始類型,突然提問可能想不全,沒必要去死記硬背,可以想一下為否的常見變數及其對應值即可。
0 | Number |
---|---|
#'' | String |
false | Boolean |
#null | Null |
undefined | Undefined |
对于不同的数据格式转换规则是不同的,我们需要分别对待。
既然是规范定义的规则,那就不要问为什么了,先大致看一下,争取记住。是在不行经常翻翻看看大佬的博客es5规范。转换有下面这么几类,我们分别看一下具体规范。(这部分转换规则,完全可以跳过去,看到下面的实例再回头看应该更容易接受一些)
转换为原始值
转换为数字
转换为字符串
ToPrimitive 运算符接受一个值,和一个可选的 期望类型 作参数。ToPrimitive 运算符把其值参数转换为非对象类型。如果对象有能力被转换为不止一种原语类型,可以使用可选的 期望类型 来暗示那个类型。根据下表完成转换
这段定义看起来有点枯燥。转换为原始值,其实就是针对引用数据的,其目的是转换为非对象类型。
如果已经是原始类型,当然就不做处理了
对于object,返回对应的原始类型,该原始类型是由期望类型决定的,期望类型其实就是我们传递的type。直接看下面比较清楚。
ToPrimitive方法大概长这么个样子具体如下。
/** * @obj 需要转换的对象 * @type 期望转换为的原始数据类型,可选 */ ToPrimitive(obj,type)
type可以为number或者string,两者的执行顺序有一些差别
string:
调用obj的toString方法,如果为原始值,则返回,否则下一步
调用obj的valueOf方法,后续同上
抛出TypeError 异常
number:
调用obj的valueOf方法,如果为原始值,则返回,否则下一步
调用obj的toString方法,后续同上
抛出TypeError 异常
其实就是调用方法先后,毕竟期望数据类型不同,如果是string当然优先调用toString。反之亦然。
当然type参数可以为空,这时候type的默认值会按照下面的规则设置
该对象为Date,则type被设置为String
否则,type被设置为Number
对于Date数据类型,我们更多期望获得的是其转为时间后的字符串,而非毫秒值,如果为number,则会取到对应的毫秒值,显然字符串使用更多。
其他类型对象按照取值的类型操作即可。
概括而言,ToPrimitive转成何种原始类型,取决于type,type参数可选,若指定,则按照指定类型转换,若不指定,默认根据实用情况分两种情况,Date为string,其余对象为number。那么什么时候会指定type类型呢,那就要看下面两种转换方式了。
某些特定情况下需要用到ToNumber方法来转成number
运算符根据下表将其参数转换为数值类型的值
对于string类型,情况比较多,只要掌握常见的就行了。和直接调用Number(str)的结果一致,这里就不多提了,主要是太多提不完。
需要注意的是,这里调用ToPrimitive的时候,type就指定为number了。下面的toString则为string。
ToString 运算符根据下表将其参数转换为字符串类型的值:
其实了解也很简单,毕竟是个规范,借用大佬一张图:
虽然是需要死记的东西,还是有些规律可循的。
对于原始值:
Undefined,null,boolean
直接加上引号,例如'null'
number 则有比较长的规范,毕竟范围比较大
常见的就是 '1' NaN则为'NaN' 基本等同于上面一条
对于负数,则返回-+字符串 例如 '-2' 其他的先不考虑了。
对象则是先转为原始值,再按照上面的步骤进行处理。
当调用 valueOf 方法,采用如下步骤:
调用ToObject方法得到一个对象O
原始数据类型转换为对应的内置对象, 引用类型则不变
调用该对象(O)内置valueOf方法.
不同内置对象的valueOf实现:
String => 返回字符串值
Number => 返回数字值
Date => 返回一个数字,即时间值,字符串中内容是依赖于具体实现的
Boolean => 返回Boolean的this值
Object => 返回this
对照代码更清晰一点
var str = new String('123') //123 console.log(str.valueOf()) var num = new Number(123) //123 console.log(num.valueOf()) var date = new Date() //1526990889729 console.log(date.valueOf()) var bool = new Boolean('123') //true console.log(bool.valueOf()) var obj = new Object({valueOf:()=>{ return 1 }}) //依赖于内部实现 console.log(obj.valueOf())
前面提了那么多抽象概念,就是为了这里来理解具体转换的。
对于+运算来说,规则如下:
+号左右分别进行取值,进行ToPrimitive()操作
分别获取左右转换之后的值,如果存在String,则对其进行ToString处理后进行拼接操作。
其他的都进行ToNumber处理
在转换时ToPrimitive,除去Date为string外都按照ToPrimitive type为Number进行处理
说的自己都迷糊了快,一起结合代码来看一下
1+'2'+false
左边取原始值,依旧是Number
中间为String,则都进行toString操作
左边转换按照toString的规则,返回'1'
得到结果temp值'12'
右边布尔值和temp同样进行1步骤
temp为string,则布尔值也转为string'false'
拼接两者 得到最后结果 '12false'
我们看一个复杂的
var obj1 = { valueOf:function(){ return 1 } } var obj2 = { toString:function(){ return 'a' } } //2 console.log(1+obj1) //1a console.log('1'+ obj2) //1a console.log(obj1+obj2)
不管多复杂,按照上面的顺序来吧。
1+obj1
左边就不说了,number
右边obj转为基础类型,按照type为number进行
先调用valueOf() 得到结果为1
两遍都是number,则进行相加得到2
1+obj2
左边为number
右边同样按照按照type为number进行转化
调用obj2.valueOf()得到的不是原始值
调用toString() return 'a'
依据第二条规则,存在string,则都转换为string进行拼接
得到结果1a
obj1+obj2
两边都是引用,进行转换 ToPrimitive 默认type为number
obj1.valueOf()为1 直接返回
obj2.valueOf()得到的不是原始值
调用toString() return 'a'
依据第二条规则,存在string,则都转换为string进行拼接
得到结果1a
到这里相信大家对+这种运算的类型转换了解的差不多了。下面就看一下另一种隐式类型转换
这种比较分为两大类,
类型相同
类型不同
相同的就不说了,隐式转换发生在不同类型之间。规律比较复杂,规范比较长,这里也不列举了,大家可以查看抽象相等算法。简单总结一句,相等比较就不想+运算那样string优先了,是以number优先级为最高。概括而言就是,都尽量转成number来进行处理,这样也可以理解,毕竟比较还是期望比较数值。那么规则大概如下:
对于x == y
如果x,y均为number,直接比较
没什么可解释的了 1 == 2 //false
如果存在对象,ToPrimitive() type为number进行转换,再进行后面比较
var obj1 = { valueOf:function(){ return '1' } } 1 == obj2 //true //obj1转为原始值,调用obj1.valueOf() //返回原始值'1' //'1'toNumber得到 1 然后比较 1 == 1 [] == ![] //true //[]作为对象ToPrimitive得到 '' //![]作为boolean转换得到0 //'' == 0 //转换为 0==0 //true
存在boolean,按照ToNumber将boolean转换为1或者0,再进行后面比较
//boolean 先转成number,按照上面的规则得到1 //3 == 1 false //0 == 0 true 3 == true // false '0' == false //true
如果x为string,y为number,x转成number进行比较
//'0' toNumber()得到 0 //0 == 0 true '0' == 0 //true
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是js隱式類型轉換使用步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!