隱式數(shù)據(jù)類型轉(zhuǎn)換介紹
前面有總結(jié)過 JS數(shù)據(jù)類型轉(zhuǎn)換 Number()
, toString()
, parseInt()
等都是屬于強(qiáng)制轉(zhuǎn)換葛假。有時(shí)我們遇到當(dāng)運(yùn)算符在運(yùn)算時(shí),如果兩邊數(shù)據(jù)類型不統(tǒng)一狂塘,CPU無法計(jì)算,這是編譯器會(huì)自動(dòng)將運(yùn)算符兩邊的數(shù)據(jù)做一個(gè)數(shù)據(jù)類型轉(zhuǎn)換,轉(zhuǎn)換成一樣的數(shù)據(jù)類型在進(jìn)行運(yùn)算谷朝,這種無需程序員手動(dòng)轉(zhuǎn)換斜姥,而由編譯器自動(dòng)轉(zhuǎn)換的方式就稱為隱式轉(zhuǎn)換鸿竖。
隱式轉(zhuǎn)換規(guī)則
1.轉(zhuǎn)為number類型:+
-
*
/
++
--
(算數(shù)運(yùn)算符) >
<
>=
<=
==
!=
===
!==
(比較運(yùn)算符)沧竟;
2.轉(zhuǎn)為string類型:+
不僅是算術(shù)運(yùn)算符,還可以做為字符串連接符把數(shù)據(jù)轉(zhuǎn)換成string類型缚忧;
3.轉(zhuǎn)為boolean類型: !
(邏輯非運(yùn)算符)
另外需要補(bǔ)充的一點(diǎn)常用的幾種運(yùn)算符各運(yùn)算符優(yōu)先級(jí):
算術(shù)運(yùn)算符:+
-
*
/
++
--
比較運(yùn)算符: >
<
>=
<=
==
!=
===
!==
邏輯運(yùn)算符:&&
||
!
賦值運(yùn)算符:=
+=
-=
*=
/=
算術(shù)運(yùn)算符 > 比較運(yùn)算符 > 邏輯運(yùn)算符 > 賦值運(yùn)算符
字符串連接符與算術(shù)隱式轉(zhuǎn)換規(guī)則混淆
console.log(1 + true); //2
console.log(1 + "true"); //"1true"
console.log(1 + undefined); //NaN
console.log(1 + null); //1
+
兩邊有一邊是字符串悟泵,那這個(gè)+
就是字符串連接符,它會(huì)把其他數(shù)據(jù)類型調(diào)用String()
方法轉(zhuǎn)成字符串然后拼接闪水;
+
做為算術(shù)運(yùn)算符會(huì)把其他數(shù)據(jù)類型調(diào)用Number()
轉(zhuǎn)成數(shù)字然后做加法運(yùn)算;
布爾值true
會(huì)被轉(zhuǎn)換數(shù)字 1
糕非,
undefined
會(huì)被轉(zhuǎn)換為 NaN
,
null
會(huì)轉(zhuǎn)換為數(shù)字 0
比較運(yùn)算符會(huì)把其他數(shù)據(jù)類型轉(zhuǎn)換number數(shù)據(jù)類型后再比較
console.log("2" > 10); //false
console.log("a" > 10); //false
console.log(10 > "a"); //false
console.log(Number("a")); //NaN
console.log("2" > "10"); //true '2'.charCodeAt() > '10'.charCodeAt() = 50 > 49 = true
console.log(false == 0); //true
console.log(false == ""); //true
console.log(Number(false)); //0
console.log(NaN == NaN); //false
console.log(undefined == null); //true
console.log(Number(NaN)); //NaN
console.log(Number(undefined)); //NaN
console.log(Number(null)) //0
比較運(yùn)算符的一邊是字符串的時(shí)候球榆,會(huì)調(diào)用 Number()
方法把字符串轉(zhuǎn)換成數(shù)字在進(jìn)行比較朽肥;
當(dāng)關(guān)系運(yùn)算符兩邊都是字符串的時(shí)候,此時(shí)同時(shí)轉(zhuǎn)成number然后比較關(guān)系持钉。重點(diǎn):此時(shí)并不是按照Number()的形式轉(zhuǎn)成數(shù)字衡招,而是按照字符串對(duì)應(yīng)的unicode編碼來轉(zhuǎn)成數(shù)字,使用 字符串.charCodeAt(字符下標(biāo)每强,默認(rèn)為0)
方法可以查看字符的unicode編碼始腾。
布爾值和數(shù)字比較時(shí),會(huì)把布爾值通過 Number()
轉(zhuǎn)成數(shù)字再進(jìn)行比較空执,true
轉(zhuǎn)成 1
浪箭,false
轉(zhuǎn)成 0
;
字符串和布爾值比較時(shí)辨绊,會(huì)把字符串和布爾值都通過 Number()
轉(zhuǎn)成數(shù)字再進(jìn)行比較
在javascript中有兩種特殊情況無視規(guī)則:1. null == undefined
山林; 2. NaN
和誰都不相等,包括他自己
復(fù)雜數(shù)據(jù)類型的隱式轉(zhuǎn)換
復(fù)雜數(shù)據(jù)類型轉(zhuǎn)成number數(shù)據(jù)類型:
1.先使用 valueOf()
方法獲取原始值邢羔,如果原始值不是number數(shù)據(jù)類型驼抹,則使用 toString()
方法轉(zhuǎn)成string;
2.再通過 Number()
方法裝成number數(shù)據(jù)類型
需要注意的:空數(shù)組的toString()方法會(huì)得到空字符串拜鹤,而空對(duì)象的toString()方法會(huì)得到字符串[object Object]
console.log([1,2] == '1,2'); //true 先將左邊數(shù)組轉(zhuǎn)成string框冀,然后右邊也是string則轉(zhuǎn)成unicode編碼運(yùn)算
console.log([] == 0); //true 默認(rèn)通過同String()轉(zhuǎn)成空字符串,再通過Number("")轉(zhuǎn)成0
var a = {};
console.log(a == 0); //false
console.log(a.valueOf().toString()); //"[object Object]"
邏輯非隱式轉(zhuǎn)換和比較運(yùn)算符隱式轉(zhuǎn)換搞混淆
0
敏簿、-0
明也、NaN
、undefined
惯裕、null
温数、""
(空字符串)這幾種情況轉(zhuǎn)換布爾類型會(huì)得到 false
,除了這幾種情況外所有數(shù)據(jù)類型都會(huì)得到 true
//大坑
console.log ( [] == 0 ); //true
console.log ( ! [] == 0 ); //true
//神坑
console.log ( [] == ! [] ); //true
console.log ( [] == [] ); //false
//史詩(shī)級(jí)坑
console.log({} == !{}); //false
console.log({} == {}); //false
[]
與 0
比較:
(1)[].valueOf().toString()
得到空字符串
(2)Number("") == 0
成立
![]
與 0
比較:
(1)邏輯非優(yōu)先級(jí)高于關(guān)系運(yùn)算符 ![] = false
(空數(shù)組轉(zhuǎn)布爾得到true蜻势,然后取反得到false)
(2)false == 0
成立
[]
與 ![]
比較:
(1) [].valueOf().toString()
得到空字符串 ""
(2) ![] = false
(3) Number("") == Number(false)
成立 都是0
[]
與 []
比較:
引用類型數(shù)據(jù)存在堆內(nèi)存中撑刺,棧內(nèi)存中存儲(chǔ)的是地址,所以他們的結(jié)果是false
{}
與 !{}
比較:
(1) {}.valueOf().toString()
得到字符串'[object Object]'
(2) !{} = false
(3) Number('[object Object]') == Number(false)
不成立握玛,因?yàn)檗D(zhuǎn)換到最后 是NaN
和 0
比較够傍,所以結(jié)果為 false
{}
與 {}
比較:
引用類型數(shù)據(jù)存在堆內(nèi)存中甫菠,棧內(nèi)存中存儲(chǔ)的是地址,所以他們的結(jié)果是false