在JavaScript中什麼時候使用==是正確的?
在JavaScript中什麼情況下使用==是正確的?簡而言之:沒有。這篇文章來看五種情況下總是使用===,並且解釋為什麼不用==。
JavaScript有兩種操作符用來比較兩個值是否相等 [1]:
- 嚴格相等 === 僅考慮相同型別的值是否相等。
- “正常”(或非嚴格)相等操作符 == 在比較之前,嘗試為不同型別的值進行轉換,然後類似嚴格相等。
給JavaScript初學者的建議是完全忘掉 == ,並且總是使用 ===。事實證明,後者是更符合常規的。有五種案例,表面看起來可以不遵從規則,但真的不是這樣。從現在開始,我使用下面的規則:
意圖清晰的程式碼勝過更簡潔的程式碼。 記住:你的程式碼僅寫一次,但被閱讀很多次——儘可能保證對閱讀者友好。
例1:你清楚自己在比較什麼
例如,使用typeof操作符[2],你能確保結果是字串。然後可以放心使用 ==,因為我們確定不會在發生型別轉換。
if (typeof x == "function") {
...
}
然而,有兩個反對這樣做的原因:
- 一致性:使用==對一致性沒有任何好處,那麼為什麼不避免使用呢?
- 簡單和效能:一般來說,=== 是最簡單的操作符,因為它不進行型別轉換。JavaScript引擎的效能參差不齊[3],但在大部分瀏覽器中 === 比 == 速度更快。
例2:與undefined和null做比較
當使用 == 時,undefined和null在結果上等價——他們彼此相等,互相相等,但沒有意義(包括JavaScript中的能被轉換為false的值):
> null == null
true
> undefined == null
true
> false == null
false
> 0 == null
false
因此,下面的if語句檢測的是null或undefined。
if (x == null) {
...
}
然而,這是否出於簡潔性考慮,意圖並不清晰:如果你同時也檢測undefined,那麼你可以這樣寫。然而,如果JavaScript初學者讀到你的程式碼,他們可能認為你僅僅檢測null。如果高手讀到你的程式碼,他們可能認為你寫錯了,並且應該寫成 ===。
if (x === undefined || x === null) {
...
}
如果你有點懶的話,上面的程式碼能被精簡為:
if (!x) {
...
}
和上面一樣的警告:這條件成立,如果x有否定型別的值。
undefined
null
false
0
""
例3:比較字串和數字
場景:你正工作在使用者介面程式碼或編碼處理伺服器端引數。你可能會把數字編碼為字串。如果x是一個字串,你可以像下面這樣比較:
if (x == 123) {
...
}
但問什麼不告訴其他閱讀你程式碼的人,如果x不是數字,它將被轉換為數字?
if (Number(x) === 123) {
...
}
例4:比較物件和原始值
使用 == 時你可以將一個原始值和其他原始值或包裝型別 [4]例項做比較:
> function isAbc(x) { return x == "abc" }
> isAbc("abc")
true
> isAbc(new String("abc"))
true
而使用 === 時,你不能這樣做:
> new String("abc") === "abc"
false
左邊是一個物件而右邊是原始值。因為他們型別不同所以不嚴格相等。然而,你同樣需要向閱讀你程式碼的人解釋清楚你的意圖。下面是表示式:
x == "abc"
你的目的是什麼?
- 你真的想讓一個包裝字串和右邊的字串作比較嗎?這似乎不太可能,但如果確實是這樣,你應該小心翼翼並給出文件記錄。
- 你想將x轉換為字串?那應該寫的更明確
String(x) === "abc"
- 你想提取包裝變數的原始值?那你應該考慮下面的寫法
x.valueOf() === "abc"
例5:JavaScript是靈活的語言——我的程式碼也應該這樣
理由是這樣的:我想我的程式碼像JavaScript一樣靈活。== 操作符幫我實現這一目的。例如JavaScript的靈活體現在它自動轉換值型別:
> "abc" + false
'abcfalse'
> 3 + true
4
> +"73"
73
有幾個理由反駁上述假說:
1.即使會自動轉換但並不總是按你需要的方式轉換。例如:
> !"false"
false
> 7 + "3"
'73'
> Number("")
0
2.非嚴格相等的轉換規則非常複雜:
> 2 == false
false
> 2 == true
false
> Boolean(2)
true
3.顯示轉化加上嚴格相等的程式碼更具描述性。比較:靈活的非嚴格相等。
function is123Implicit(x) {
return x == 123;
}
> is123Implicit(123)
true
> is123Implicit(new Number(123))
true
> is123Implicit("123")
true
替代方案:靈活的顯式轉換和嚴格相等。
function is123Explicit(x) {
x = Number(x);
return x === 123;
}
> is123Explicit(123)
true
> is123Explicit(new Number(123))
true
> is123Explicit("123")
true
4.有人說您的程式碼缺少靈活性?可以說JavaScript的預設靈活性利大於弊(對於學習難度而言)。寫防禦型的程式碼更容易暴漏Bug。is123Explicit()
的防禦型版本看起來像下面這樣:
function is123Defensive(x) {
if (typeof x !== "number") {
throw new TypeError("Not a number: "+x);
}
return x === 123;
}
如果你想給函式傳遞任何非原始數字值,你必須先進行型別轉換。
結論
我希望我讓你確信堅持簡單的規則——”不用 ==“的意義,不只是對新手。在你的程式碼中魔法越少,通常意味著越容易理解。
相關閱讀
- Equality in JavaScript: === versus ==
- Improving the JavaScript typeof operator
- jsPerf: == versus ===
- JavaScript values: not everything is an object
注
英文:http://www.2ality.com/2011/12/strict-equality-exemptions.html
Q群推薦
- CSS家園188275051,CSS開發者的天堂,歡迎有興趣的同學加入
- GitHub家園225932282,GitHub愛好者的天堂,歡迎有興趣的同學加入
- 碼農之家203145707,碼農的天堂,歡迎有興趣的同學加入
相關文章
- 在 JavaScript 中,什麼時候使用 Map 或勝過 ObjectJavaScriptObject
- 美國公司年審時間是在什麼時候的?
- Protobuf在Cmake中的正確使用
- session是什麼時候建立的Session
- 使用 pymysql 的時候如何正確的處理轉義字元MySql字元
- 在 JavaScript 中建立陣列的正確姿勢JavaScript陣列
- 是時候談談JavaScript物件導向了!(我們什麼時候更需要它)JavaScript物件
- python中什麼時候使用自定義類Python
- C++中什麼時候用move,什麼時候用forward?C++Forward
- 到底什麼時候使用mqMQ
- 什麼是遷移學習?什麼時候使用遷移學習?遷移學習
- 在Flutter中嵌入Native元件的正確姿勢是...Flutter元件
- [譯] JavaScript中的“this”是什麼?JavaScript
- javascript中null是什麼JavaScriptNull
- 選擇catalyst是正確的麼?
- Android中Handler的正確使用Android
- BigDecimal 在資金計算時正確使用姿勢Decimal
- 在vscode使用editorconfig的正確姿勢VSCode
- 在JavaScript中this到底指代什麼?JavaScript
- 你覺得你每天最佳的工作時間是什麼時候?
- javascript中閉包是什麼JavaScript
- javascript中web worker是什麼JavaScriptWeb
- 你是什麼時候”突然”學會程式設計的程式設計
- MySQL什麼時候會使用內部臨時表?MySql
- 什麼時候需要自動化什麼時候用自動化?
- react中什麼使用定義變數,需要使用useRef,什麼時候直接定義即可?React變數
- Flink中什麼時候需要些returns()方法
- 洞見RSAC | 什麼是威脅狩獵的正確“姿勢”?
- 為什麼黑國行NS不該是“政治正確”
- Python的類什麼時候用Python
- 什麼時候釋出
- 什麼時候能解脫
- Python會在什麼時候被其他語言取代Python
- 為什麼說是時候擁抱.NET CORE了?
- 區分import 什麼時候使用 花括號{ }Import
- javascript中window.$是什麼意思JavaScript
- 英語日期序數詞的寫法?什麼時候加st?什麼時候加th?1~31號分別是怎麼加的?
- springboot 中如何正確的在非同步執行緒中使用requestSpring Boot非同步執行緒
- 什麼時候採用socket通訊,什麼時候採用http通訊HTTP