隱式數(shù)據(jù)類型轉(zhuǎn)換介紹
前面有總結(jié)過 JS數(shù)據(jù)類型轉(zhuǎn)換 Number(), toString(), parseInt()等都是屬于強制轉(zhuǎn)換。有時我們遇到當(dāng)運算符在運算時,如果兩邊數(shù)據(jù)類型不統(tǒng)一,CPU無法計算,這是編譯器會自動將運算符兩邊的數(shù)據(jù)做一個數(shù)據(jù)類型轉(zhuǎn)換,轉(zhuǎn)換成一樣的數(shù)據(jù)類型在進行運算,這種無需程序員手動轉(zhuǎn)換,而由編譯器自動轉(zhuǎn)換的方式就稱為隱式轉(zhuǎn)換。
隱式轉(zhuǎn)換規(guī)則
1.轉(zhuǎn)為number類型:+ - * / ++ --(算數(shù)運算符) > < >= <= == != === !==(比較運算符);
2.轉(zhuǎn)為string類型:+ 不僅是算術(shù)運算符,還可以做為字符串連接符把數(shù)據(jù)轉(zhuǎn)換成string類型;
3.轉(zhuǎn)為boolean類型: !(邏輯非運算符)
另外需要補充的一點常用的幾種運算符各運算符優(yōu)先級:
算術(shù)運算符:+ - * / ++ --
比較運算符: > < >= <= == != === !==
邏輯運算符:&& || !
賦值運算符:= += -= *= /=
算術(shù)運算符 > 比較運算符 > 邏輯運算符 > 賦值運算符
字符串連接符與算術(shù)隱式轉(zhuǎn)換規(guī)則混淆
console.log(1 + true); //2
console.log(1 + "true"); //"1true"
console.log(1 + undefined); //NaN
console.log(1 + null); //1
+兩邊有一邊是字符串,那這個+就是字符串連接符,它會把其他數(shù)據(jù)類型調(diào)用String()方法轉(zhuǎn)成字符串然后拼接;
+做為算術(shù)運算符會把其他數(shù)據(jù)類型調(diào)用Number()轉(zhuǎn)成數(shù)字然后做加法運算;
布爾值true會被轉(zhuǎn)換數(shù)字 1,
undefined會被轉(zhuǎn)換為 NaN,
null會轉(zhuǎn)換為數(shù)字 0
比較運算符會把其他數(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
比較運算符的一邊是字符串的時候,會調(diào)用 Number() 方法把字符串轉(zhuǎn)換成數(shù)字在進行比較;
當(dāng)關(guān)系運算符兩邊都是字符串的時候,此時同時轉(zhuǎn)成number然后比較關(guān)系。重點:此時并不是按照Number()的形式轉(zhuǎn)成數(shù)字,而是按照字符串對應(yīng)的unicode編碼來轉(zhuǎn)成數(shù)字,使用 字符串.charCodeAt(字符下標(biāo),默認(rèn)為0) 方法可以查看字符的unicode編碼。
布爾值和數(shù)字比較時,會把布爾值通過 Number() 轉(zhuǎn)成數(shù)字再進行比較,true轉(zhuǎn)成 1,false 轉(zhuǎn)成 0;
字符串和布爾值比較時,會把字符串和布爾值都通過 Number() 轉(zhuǎn)成數(shù)字再進行比較
在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()方法會得到空字符串,而空對象的toString()方法會得到字符串[object Object]
console.log([1,2] == '1,2'); //true 先將左邊數(shù)組轉(zhuǎn)成string,然后右邊也是string則轉(zhuǎn)成unicode編碼運算
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)換和比較運算符隱式轉(zhuǎn)換搞混淆
0、-0、NaN、undefined、null、""(空字符串)這幾種情況轉(zhuǎn)換布爾類型會得到 false,除了這幾種情況外所有數(shù)據(jù)類型都會得到 true
//大坑
console.log ( [] == 0 ); //true
console.log ( ! [] == 0 ); //true
//神坑
console.log ( [] == ! [] ); //true
console.log ( [] == [] ); //false
//史詩級坑
console.log({} == !{}); //false
console.log({} == {}); //false
[] 與 0比較:
(1)[].valueOf().toString() 得到空字符串
(2)Number("") == 0 成立
![] 與 0比較:
(1)邏輯非優(yōu)先級高于關(guā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)存中存儲的是地址,所以他們的結(jié)果是false
{} 與 !{}比較:
(1) {}.valueOf().toString() 得到字符串'[object Object]'
(2) !{} = false
(3) Number('[object Object]') == Number(false) 不成立,因為轉(zhuǎn)換到最后 是NaN 和 0比較,所以結(jié)果為 false
{} 與 {}比較:
引用類型數(shù)據(jù)存在堆內(nèi)存中,棧內(nèi)存中存儲的是地址,所以他們的結(jié)果是false