抽象相等操作符 ("loose equality","double equals") 掠哥,即 == 巩踏,相信大家伙兒都不陌生,我們都知道它比較的兩個操作數(shù)如果是不同類型的续搀,就會嘗試在比較之前將它們轉(zhuǎn)換為相同類型(原始值)塞琼。
比如:如果操作數(shù)之一是對象,另一個是數(shù)字或字符串禁舷,會嘗試使用對象的 valueOf() 彪杉,若無法轉(zhuǎn)換成原始值,再調(diào)用對象的 toString() 方法將對象轉(zhuǎn)換為原始值牵咙。
舉個例子:
// 阿里派近、百度、騰訊面試題
// ? 位置應(yīng)該怎么寫才能輸出 true
var a = ?;
console.log(
a == 1 &&
a == 2 &&
a == 3
);
分析:這道題是在考抽象相等操作符(==)的運算規(guī)則以及類型轉(zhuǎn)換的規(guī)則洁桌,那么我們開始嘗試一下渴丸。
先貼一下 == 操作符的判斷規(guī)則:
● 如果兩個操作數(shù)都是對象,則僅當兩個操作數(shù)都引用同一個對象時才返回 true。
● 如果一個操作數(shù)是 null曙强,另一個操作數(shù)是 undefined残拐,則返回 true。
● 如果兩個操作數(shù)是不同類型的碟嘴,就會嘗試在比較之前將它們轉(zhuǎn)換為相同類型:
○ ○ 當數(shù)字與字符串進行比較時,會嘗試將字符串轉(zhuǎn)換為數(shù)字值娜扇。
○ ○ 如果操作數(shù)之一是 Boolean错沃,則將布爾操作數(shù)轉(zhuǎn)換為1或0雀瓢。
■■■ 如果是 true,則轉(zhuǎn)換為 1刃麸。
■■■ 如果是 false,則轉(zhuǎn)換為 0泊业。
○ ○ 如果操作數(shù)之一是對象把沼,另一個是數(shù)字或字符串吁伺,會嘗試使用對象的 valueOf() 和 toString() 方法將對象轉(zhuǎn)換為原始值。
● 如果操作數(shù)具有相同的類型篮奄,則將它們進行如下比較:
○ ○ String:true 僅當兩個操作數(shù)具有相同順序的相同字符時才返回。
○ ○ Number:true 僅當兩個操作數(shù)具有相同的值時才返回窟却。+0 并被 -0 視為相同的值昼丑。如果任一操作數(shù)為NaN间校,則返回 false。
○ ○ Boolean:true 僅當操作數(shù)為兩個 true 或兩個 false 時才返回 true憔足。
1胁附、a 等于 1 或 2 或 3滓彰,顯然都不行;
2揭绑、a 如果是 Boolean 值郎哭,只能轉(zhuǎn)換成 0 或 1;
3菇存、那 a 應(yīng)該是一個對象夸研,另一個值是數(shù)字,那就符合這一條判斷規(guī)則:如果兩個操作數(shù)是不同類型的依鸥,并且操作數(shù)之一是對象亥至,另一個是數(shù)字或字符串,會嘗試使用對象的 valueOf() 和 toString() 方法將對象轉(zhuǎn)換為原始值贱迟。
var a = {}
console.log(a.valueOf()) // {}
console.log(a.toString()) // "[object Object]"
// 在這里你會發(fā)現(xiàn) a 對象的 valueOf() 和 toString() 方法都不能轉(zhuǎn)換成原始值姐扮,
// 那我們就重寫 a 對象的 valueOf() 或 toString() 方法,讓它返回原始值衣吠。
var a = {
valueOf: function() {
return 1;
}
};
// 但因為是被比較了3次茶敏,所以應(yīng)該 this.value++
var a = {
value: 1,
valueOf: function() {
return this.value++;
}
};
console.log(
a == 1 &&
a == 2 &&
a == 3
); // true