W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
我們知道,在數(shù)學(xué)中有很多用于比較大小的運(yùn)算符。
在 JavaScript 中,它們的編寫方式如下:
a > b
?,?a < b
?。a >= b
?,?a <= b
?。a == b
?,請(qǐng)注意雙等號(hào) ?==
? 表示相等性檢查,而單等號(hào) ?a = b
? 表示賦值。≠
?,但在 JavaScript 中寫成 ?a != b
?。在本文中,我們將進(jìn)一步了解不同類型的比較,JavaScript 是如何進(jìn)行比較的,包括一些重要的特殊性。
在文末給出了一些秘訣,幫助你避免 “JavaScript 陷阱”相關(guān)的問(wèn)題。
所有比較運(yùn)算符均返回布爾值:
true
?—— 表示“yes(是)”,“correct(正確)”或“the truth(真)”。false
?—— 表示“no(否)”,“wrong(錯(cuò)誤)”或“not the truth(非真)”。示例:
alert( 2 > 1 ); // true(正確)
alert( 2 == 1 ); // false(錯(cuò)誤)
alert( 2 != 1 ); // true(正確)
和其他類型的值一樣,比較的結(jié)果可以被賦值給任意變量:
let result = 5 > 4; // 把比較的結(jié)果賦值給 result
alert( result ); // true
在比較字符串的大小時(shí),JavaScript 會(huì)使用“字典(dictionary)”或“詞典(lexicographical)”順序進(jìn)行判定。
換言之,字符串是按字符(母)逐個(gè)進(jìn)行比較的。
例如:
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
字符串的比較算法非常簡(jiǎn)單:
在上面的第一個(gè)例子中,'Z' > 'A'
比較在算法的第 1 步就得到了結(jié)果。
在第二個(gè)例子中,字符串 Glow
與 Glee
的比較則需要更多步驟,因?yàn)樾枰饌€(gè)字符進(jìn)行比較:
G
?和 ?G
? 相等。l
? 和 ?l
? 相等。o
? 比 ?e
? 大,算法停止,第一個(gè)字符串大于第二個(gè)。非真正的字典順序,而是 Unicode 編碼順序
在上面的算法中,比較大小的邏輯與字典或電話簿中的排序很像,但也不完全相同。
比如說(shuō),字符串比較對(duì)字母大小寫是敏感的。大寫的
"A"
并不等于小寫的"a"
。哪一個(gè)更大呢?實(shí)際上小寫的"a"
更大。這是因?yàn)樵?JavaScript 使用的內(nèi)部編碼表中(Unicode),小寫字母的字符索引值更大。我們會(huì)在 字符串 這章討論更多關(guān)于字符串的細(xì)節(jié)。
當(dāng)對(duì)不同類型的值進(jìn)行比較時(shí),JavaScript 會(huì)首先將其轉(zhuǎn)化為數(shù)字(number)再判定大小。
例如:
alert( '2' > 1 ); // true,字符串 '2' 會(huì)被轉(zhuǎn)化為數(shù)字 2
alert( '01' == 1 ); // true,字符串 '01' 會(huì)被轉(zhuǎn)化為數(shù)字 1
對(duì)于布爾類型值,true
會(huì)被轉(zhuǎn)化為 1
、false
轉(zhuǎn)化為 0
。
例如:
alert( true == 1 ); // true
alert( false == 0 ); // true
一個(gè)有趣的現(xiàn)象
有時(shí)候,以下兩種情況會(huì)同時(shí)發(fā)生:
- 若直接比較兩個(gè)值,其結(jié)果是相等的。
- 若把兩個(gè)值轉(zhuǎn)為布爾值,它們可能得出完全相反的結(jié)果,即一個(gè)是 ?
true
?,一個(gè)是 ?false
?。例如:
let a = 0; alert( Boolean(a) ); // false let b = "0"; alert( Boolean(b) ); // true alert(a == b); // true!
對(duì)于 JavaScript 而言,這種現(xiàn)象其實(shí)挺正常的。因?yàn)?JavaScript 會(huì)把待比較的值轉(zhuǎn)化為數(shù)字后再做比較(因此
"0"
變成了0
)。若只是將一個(gè)變量轉(zhuǎn)化為Boolean
值,則會(huì)使用其他的類型轉(zhuǎn)換規(guī)則。
普通的相等性檢查 ==
存在一個(gè)問(wèn)題,它不能區(qū)分出 0
和 false
:
alert( 0 == false ); // true
也同樣無(wú)法區(qū)分空字符串和 false
:
alert( '' == false ); // true
這是因?yàn)樵诒容^不同類型的值時(shí),處于相等判斷符號(hào) ==
兩側(cè)的值會(huì)先被轉(zhuǎn)化為數(shù)字。空字符串和 false
也是如此,轉(zhuǎn)化后它們都為數(shù)字 0。
如果我們需要區(qū)分 0
和 false
,該怎么辦?
嚴(yán)格相等運(yùn)算符 ===
在進(jìn)行比較時(shí)不會(huì)做任何的類型轉(zhuǎn)換。
換句話說(shuō),如果 a
和 b
屬于不同的數(shù)據(jù)類型,那么 a === b
不會(huì)做任何的類型轉(zhuǎn)換而立刻返回 false
。
讓我們?cè)囋嚕?
alert( 0 === false ); // false,因?yàn)楸槐容^值的數(shù)據(jù)類型不同
同樣的,與“不相等”符號(hào) !=
類似,“嚴(yán)格不相等”表示為 !==
。
嚴(yán)格相等的運(yùn)算符雖然寫起來(lái)稍微長(zhǎng)一些,但是它能夠很清楚地顯示代碼意圖,降低你犯錯(cuò)的可能性。
當(dāng)使用 null
或 undefined
與其他值進(jìn)行比較時(shí),其返回結(jié)果常常出乎你的意料。
當(dāng)使用嚴(yán)格相等 ===
比較二者時(shí)
它們不相等,因?yàn)樗鼈儗儆诓煌念愋汀?
alert( null === undefined ); // false
當(dāng)使用非嚴(yán)格相等 ==
比較二者時(shí)
JavaScript 存在一個(gè)特殊的規(guī)則,會(huì)判定它們相等。它們倆就像“一對(duì)戀人”,僅僅等于對(duì)方而不等于其他任何的值(只在非嚴(yán)格相等下成立)。
alert( null == undefined ); // true
當(dāng)使用數(shù)學(xué)式或其他比較方法 < > <= >=
時(shí):
null/undefined
會(huì)被轉(zhuǎn)化為數(shù)字:null
被轉(zhuǎn)化為 0
,undefined
被轉(zhuǎn)化為 NaN
。
下面讓我們看看,這些規(guī)則會(huì)帶來(lái)什么有趣的現(xiàn)象。同時(shí)更重要的是,我們需要從中學(xué)會(huì)如何遠(yuǎn)離這些特性帶來(lái)的“陷阱”。
通過(guò)比較 null
和 0 可得:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
是的,上面的結(jié)果完全打破了你對(duì)數(shù)學(xué)的認(rèn)識(shí)。在最后一行代碼顯示“null
大于等于 0”的情況下,前兩行代碼中一定會(huì)有一個(gè)是正確的,然而事實(shí)表明它們的結(jié)果都是 false。
為什么會(huì)出現(xiàn)這種反常結(jié)果,這是因?yàn)橄嗟刃詸z查 ==
和普通比較符 > < >= <=
的代碼邏輯是相互獨(dú)立的。進(jìn)行值的比較時(shí),null
會(huì)被轉(zhuǎn)化為數(shù)字,因此它被轉(zhuǎn)化為了 0
。這就是為什么(3)中 null >= 0
返回值是 true,(1)中 null > 0
返回值是
false。
另一方面,undefined
和 null
在相等性檢查 ==
中不會(huì)進(jìn)行任何的類型轉(zhuǎn)換,它們有自己獨(dú)立的比較規(guī)則,所以除了它們之間互等外,不會(huì)等于任何其他的值。這就解釋了為什么(2)中 null == 0
會(huì)返回 false。
undefined
不應(yīng)該被與其他值進(jìn)行比較:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
為何它看起來(lái)如此厭惡 0?返回值都是 false!
原因如下:
(1)
? 和 ?(2)
? 都返回 ?false
?是因?yàn)?nbsp;?undefined
?在比較中被轉(zhuǎn)換為了 ?NaN
?,而 ?NaN
?是一個(gè)特殊的數(shù)值型值,它與任何值進(jìn)行比較都會(huì)返回 ?false
?。(3)
? 返回 ?false
?是因?yàn)檫@是一個(gè)相等性檢查,而 ?undefined
?只與 ?null
?相等,不會(huì)與其他值相等。我們?yōu)楹我芯可鲜鍪纠课覀冃枰獣r(shí)刻記得這些古怪的規(guī)則嗎?不,其實(shí)不需要。雖然隨著代碼寫得越來(lái)越多,我們對(duì)這些規(guī)則也都會(huì)爛熟于胸,但是我們需要更為可靠的方法來(lái)避免潛在的問(wèn)題:
===
? 外,其他但凡是有 ?undefined/null
? 參與的比較,我們都需要格外小心。>= > < <=
? 去比較一個(gè)可能為 ?null/undefined
? 的變量。對(duì)于取值可能是 ?null/undefined
? 的變量,請(qǐng)按需要分別檢查它的取值情況。==
? 下,?null
?和 ?undefined
?相等且各自不等于任何其他的值。>
? 或 ?<
? 進(jìn)行比較時(shí),需要注意變量可能為 ?null/undefined
? 的情況。比較好的方法是單獨(dú)檢查變量是否等于 ?null/undefined
?。重要程度: 5
以下表達(dá)式的執(zhí)行結(jié)果是?
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false
結(jié)果的原因:
"a"
? 比 ?"p"
? 小。"2"
? 大于 ?"1"
?。null
?只與 ?undefined
?互等。null
?只與 ?undefined
?相等。Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: