在JavaScript中什么情況下使用==是正確的?簡而言之:沒有。這篇文章來看五種情況下總是使用===,并且解釋為什么不用==。
JavaScript有兩種操作符用來比較兩個(gè)值是否相等 [1]:
給JavaScript初學(xué)者的建議是完全忘掉 == ,并且總是使用 ===。事實(shí)證明,后者是更符合常規(guī)的。有五種案例,表面看起來可以不遵從規(guī)則,但真的不是這樣。從現(xiàn)在開始,我使用下面的規(guī)則:
意圖清晰的代碼勝過更簡潔的代碼。 記?。耗愕拇a僅寫一次,但被閱讀很多次——盡可能保證對閱讀者友好。
例如,使用typeof操作符[2],你能確保結(jié)果是字符串。然后可以放心使用 ==,因?yàn)槲覀兇_定不會在發(fā)生類型轉(zhuǎn)換。
if (typeof x == "function") {
...
}
然而,有兩個(gè)反對這樣做的原因:
當(dāng)使用 == 時(shí),undefined和null在結(jié)果上等價(jià)——他們彼此相等,互相相等,但沒有意義(包括JavaScript中的能被轉(zhuǎn)換為false的值):
> null == null
true
> undefined == null
true
> false == null
false
> 0 == null
false
因此,下面的if語句檢測的是null或undefined。
if (x == null) {
...
}
然而,這是否出于簡潔性考慮,意圖并不清晰:如果你同時(shí)也檢測undefined,那么你可以這樣寫。然而,如果JavaScript初學(xué)者讀到你的代碼,他們可能認(rèn)為你僅僅檢測null。如果高手讀到你的代碼,他們可能認(rèn)為你寫錯(cuò)了,并且應(yīng)該寫成 ===。
if (x === undefined || x === null) {
...
}
如果你有點(diǎn)懶的話,上面的代碼能被精簡為:
if (!x) {
...
}
和上面一樣的警告:這條件成立,如果x有否定類型的值。
undefined
null
false
0
""
場景:你正工作在用戶界面代碼或編碼處理服務(wù)器端參數(shù)。你可能會把數(shù)字編碼為字符串。如果x是一個(gè)字符串,你可以像下面這樣比較:
if (x == 123) {
...
}
但問什么不告訴其他閱讀你代碼的人,如果x不是數(shù)字,它將被轉(zhuǎn)換為數(shù)字?
if (Number(x) === 123) {
...
}
使用 == 時(shí)你可以將一個(gè)原始值和其他原始值或包裝類型 [4]實(shí)例做比較:
> function isAbc(x) { return x == "abc" }
> isAbc("abc")
true
> isAbc(new String("abc"))
true
而使用 === 時(shí),你不能這樣做:
> new String("abc") === "abc"
false
左邊是一個(gè)對象而右邊是原始值。因?yàn)樗麄冾愋筒煌圆粐?yán)格相等。然而,你同樣需要向閱讀你代碼的人解釋清楚你的意圖。下面是表達(dá)式:
x == "abc"
你的目的是什么?
String(x) === "abc"
x.valueOf() === "abc"
理由是這樣的:我想我的代碼像JavaScript一樣靈活。== 操作符幫我實(shí)現(xiàn)這一目的。例如JavaScript的靈活體現(xiàn)在它自動轉(zhuǎn)換值類型:
> "abc" + false
'abcfalse'
> 3 + true
4
> +"73"
73
有幾個(gè)理由反駁上述假說:
1.即使會自動轉(zhuǎn)換但并不總是按你需要的方式轉(zhuǎn)換。例如:
> !"false"
false
> 7 + "3"
'73'
> Number("")
0
2.非嚴(yán)格相等的轉(zhuǎn)換規(guī)則非常復(fù)雜:
> 2 == false
false
> 2 == true
false
> Boolean(2)
true
3.顯示轉(zhuǎn)化加上嚴(yán)格相等的代碼更具描述性。比較:靈活的非嚴(yán)格相等。
function is123Implicit(x) {
return x == 123;
}
> is123Implicit(123)
true
> is123Implicit(new Number(123))
true
> is123Implicit("123")
true
替代方案:靈活的顯式轉(zhuǎn)換和嚴(yán)格相等。
function is123Explicit(x) {
x = Number(x);
return x === 123;
}
> is123Explicit(123)
true
> is123Explicit(new Number(123))
true
> is123Explicit("123")
true
4.有人說您的代碼缺少靈活性?可以說JavaScript的默認(rèn)靈活性利大于弊(對于學(xué)習(xí)難度而言)。寫防御型的代碼更容易暴漏Bug。is123Explicit()
的防御型版本看起來像下面這樣:
function is123Defensive(x) {
if (typeof x !== "number") {
throw new TypeError("Not a number: "+x);
}
return x === 123;
}
如果你想給函數(shù)傳遞任何非原始數(shù)字值,你必須先進(jìn)行類型轉(zhuǎn)換。
我希望我讓你確信堅(jiān)持簡單的規(guī)則——”不用 ==“的意義,不只是對新手。在你的代碼中魔法越少,通常意味著越容易理解。
英文:http://www.2ality.com/2011/12/strict-equality-exemptions.html
更多建議: