==的類型轉換主要分爲兩類,x、y類型相同時,和類型不相同時。markdown
類型相同時,沒有類型轉換,主要注意NaN不與任何值相等,包括它本身,即NaN !== NaN。函數
類型不相同時:this
一、x,y 爲null、undefined二者中一個 // 返回truespa
二、x、y爲Number和String類型時,則轉換爲Number類型比較。prototype
三、有Boolean類型時,Boolean轉化爲Number類型比較。code
四、一個Object類型,一個String或Number類型,將Object類型進行原始轉換後,按上面流程進行原始值比較。orm
var a = {
valueOf: function () {
return 1;
},
toString: function () {
return '123'
}
}
true == a ;// true;
複製代碼
首先,x與y類型不一樣,x爲boolean類型,則進行ToNumber轉換爲1,爲number類型。 接着,x爲number,y爲object類型,對y進行原始轉換,ToPrimitive(a, ?),沒有指定轉換類型,默認number類型。 然後,ToPrimitive(a, Number)首先調用valueOf方法,返回1,獲得原始類型1。 最後 1 == 1, 返回true。繼承
[] == !{}
複製代碼
一、! 運算符優先級高於==,故先進行!運算。 二、!{}運算結果爲false,結果變成 [] == false比較。 三、等式右邊y = ToNumber(false) = 0。結果變成 [] == 0。 四、比較變成ToPrimitive([]) == 0。 進行原始值轉換,[]會先調用valueOf函數,返回this。 不是原始值,繼續調用toString方法,x = [].toString() = ‘’。 故結果爲 ‘’ == 0比較。 五、根據上面第5條,等式左邊x = ToNumber(‘’) = 0。 因此結果變爲: 0 == 0,返回true,比較結束。it
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('hello world!');
}
複製代碼
一、當執行a == 1 && a == 2 && a == 3 時,會從左到右一步一步解析,首先 a == 1,會進行ToPrimitive(a, Number) == 1。io
二、ToPrimitive(a, Number),按照上面原始類型轉換規則,會先調用valueOf方法,a的valueOf方法繼承自Object.prototype。返回a自己,而非原始類型,故會調用toString方法。
三、由於toString被重寫,因此會調用重寫的toString方法,故返回1,注意這裏是i++,而不是++i,它會先返回i,在將i+1。故ToPrimitive(a, Number) = 1。也就是1 == 1,此時i = 1 + 1 = 2。
四、執行完a == 1返回true,會執行a == 2,同理,會調用ToPrimitive(a, Number),同上先調用valueOf方法,在調用toString方法,因爲第一步,i = 2此時,ToPrimitive(a, Number) = 2, 也就是2 == 2, 此時i = 2 + 1。
五、同上能夠推導 a == 3也返回true。故最終結果 a == 1 && a == 2 && a == 3返回true