javascript中神奇的隱式轉換
最常見的==和!=造成的隱式轉換,網上已經有很多人總結了,總結起來就一張圖:
Object → String → Number
↑
Boolean
不同型別之間做==或!=運算,會按箭頭方向轉換直到型別相等。
(undefined, null和NaN後面再細說)
下面是重點,到底哪些運算會造成隱式轉換呢?
按照我的理解,除了===和!==比較運算,其他所有的運算都會造成隱式轉換。
JS的運算子可以歸納為7大類:
1. 算術運算子
2. 賦值運算子
3. 比較運算子
4. 邏輯運算子
5. 三元運算子
6. 位運算子
7. 字串連線運算子
我們來逐個驗證。
1.算術運算子
+, -, *, /, %, ++, –
轉換規則1:所有型別均轉換為Number;
轉換規則2:null會轉換為0,undefined會轉換為NaN
console.log(null + 1); //1 +運算子作為字串連線符的例子請看第7條
console.log(undefined - 1); // NaN
console.log([] * 1); //0 []先轉換為String:'',再轉換為0
console.log([1] / 1); //1 [1]先轉換為String:'1',再轉換為1
console.log({} % 1); //NaN {}先轉換為String:'[object Object]',再轉換為NaN:
var a = true; console.log(++a); //2 不能寫成++true, ++運算只能作用於變數
var a = false; console.log(--a); //-1
2.賦值運算子
=,+=,-=,*=,/=,%=
賦值運算的隱式轉換與算術運算同理,這裡就不再驗證了。
3.比較運算子
==, !=, >, >=, <, <=(不討論絕對等於)
轉換規則1:若均為基本型別,不需轉換;若均為複雜型別,做>和<比較需轉換為String再比較;
轉換規則2:若型別不同,按照最上圖進行轉換,直到型別相等,最終轉換為String或Number;
比較規則1:Number直接比較;String逐字元比較他們的unicode值;複雜型別比較引用的物件是否相同。
比較規則2:NaN既不等於任何值,也不大於和小於任何值;
比較規則3:undefined == null 返回true,兩者和除此之外所有型別都不相等。
console.log('true' == true); //false 均轉換為Number,既 NaN == 1
console.log([] != true); //true 均轉換為Number,既 0 != 1
console.log('a' > 1); //false 均轉換為Number,既NaN>1
console.log('a' > '1'); //true 直接比較unicode值
4.三元運算子
a ? b : c
轉換規則1:第一個值會轉換為Boolean;
轉換規則2: 空字串/0/null/NaN/undefined會轉換為false,其他為true
console.log( [] ? 1 : 2); //1
5.邏輯運算子
&&, ||, !
&& 和 || 轉換規則:所有型別均先轉換為Boolean做運算,再根據各自運算規則返回其中的一個原值;
! 轉換規則:所有型別均轉換為Boolean,並返回該Boolean的取反
console.log(undefined && 1); //undefined
console.log({} || 'a'); //Object {}
console.log(!undefined); //true
6.位運算子
~, &, |, ^, <<, >>, >>>
轉換規則1:所有型別均轉換為Number;
轉換規則2:NaN, null和undefined都會轉換為0(注意,與算術運算子不同)
console.log(~undefined); //-1
console.log('25'&[3]); //1
console.log({}|NaN); //0
console.log({}^[1]); //1
console.log(NaN<<1); //0
console.log({}>>1); //0
console.log(['6.6']>>>0); //6
7.字串連線運算子
+
轉換規則:若運算子前後有一個為複雜型別或String型別,兩者均轉換為String型別
console.log(null+[]+1); //null1
這麼多的隱式轉換,簡直是防不勝防。
那麼為什麼只有==這個運算的隱式轉換這麼受人關注呢?
一個原因是,其他運算子造成的隱式轉換就是我們想要的,比如算術運算子我們就是想得到Number,但是==運算不同,它的隱式轉換並不可控,出的意外更多;
另一個原因是,我們完全可以用===來避免這種隱式轉換,而其他的運算子就沒有這種待遇了。