JavaScript 中的==
運算符用以比較兩側的值是否“近似”相等,區別於===
的嚴格相等。
==
可以達到以下效果:
null==undefined //true
[]==false //true
[]=='' //true
[1]=='1' //true
要說明 JavaScript 引擎在計算 ==
運算符時做了什麼,先要了解幾個內部概念和方法。
Type
ECMAScript 規範規定了六種變量類型:null,undefined,string,number,boolean,object。Type
不同於運算符 typeof
,它可以分辨出
null 和 object,但不能分辨 function 和 object,當然事實上並沒有 function 這樣一種類型。
可以這樣模擬 Type
的行爲:
function Type(e) {
if (undefined === e) {
return 'undefined';
} else if (null === e) {
return 'null';
} else if ('number' === typeof e) {
return 'number';
} else if ('string' === typeof e) {
return 'string';
} else if ('boolean' === typeof e) {
return 'boolean';
} else return 'object';
}
0的符號
另外需要說明的是0本身包括兩個值,正零:+0,和負零:-0。一般不會對這兩個值進行區分,甚至使用 ===
運算符也分辨不出:
+0===-0 //true
在ECMAScript中有內部內部方法可以區別出這兩個值,當然我們也可以做到這一點:
function isPositiveZero(e) {
return 0 === e && 1 / e > 0;
}
function isNegativeZero(e) {
return 0 === e && 1 / e < 0;
}
關於這兩點將會在後面的偵斷中用到。
ToNumber
轉換爲數字,規則如下:
輸入類型 | 結果 |
---|---|
Undefined | NaN |
Null | +0 |
Boolean | 真返回1,假返回+0 |
Number | 直接返回 |
String | 字面意義 |
Object | 調用ToNumber(toPrimitive),hint:Number |
toPrimitive
該內部方法將一個對象轉換爲原始類型,在上面提到的六種類型中,前五種都屬於原始類型。對於非原始類型,將根據一個成爲hint
的值訪問該對象的 Default
Value
屬性來獲取原始值。hint
取值只能爲
“string” 和 “number”(默認)。如果爲 “string”,將依次調用對象的 toString
和 valueOf
來獲取原始值,如果爲
“number”,將依次調用 valueOf
和 toString
方法,可見順序依賴於 hint
值。
==
==
操作x,y兩個值時要經過一系列的類型和值的偵斷,在
ECMAScript 內部稱之爲 The
Abstract Equality Comparison Algorithm
:
- 如果 Type(x) 不同於 Type(y), 執行第 14 步。
- 如果 Type(x) 爲 Undefined, 返回真。
- 如果 Type(x) 爲 Null, 返回真。
- 如果 Type(x) 不是 Number, 執行第 11 步。
- 如果 x 爲 NaN, 返回假。
- 如果 y 爲 NaN, 返回假。
- 如果 x 與 y 有相同的值, 返回真。
- 如果 x 爲 +0 並且 y 爲 −0, 返回真。
- 如果 x 爲 −0 並且 y 爲 +0, 返回真。
- 返回假。
- 如果 Type(x) 爲 String, 那麼如果 x 和 y 具有相同的字符序列(等長並且對應位置字符相同)返回真,否則,返回假。
- 如果 Type(x) 爲 Boolean, 如果 x 和 y 都是真或者都是假則返回真,否則,返回假。
- 如果x和y引用相同的對象返回真,否則, 返回假。
- 如果 x 爲 null 並且 y 爲 undefined, 返回真。
- 如果 x 爲 undefined 並且 y 爲 null, 返回真。
- 如果 Type(x) 爲 Number 並且 Type(y) 爲 String,返回 x == ToNumber(y) 的結果。
- 如果 Type(x) 爲 String 並且 Type(y) 爲 Number,返回 ToNumber(x) == y 的結果。
- 如果 Type(x) 爲 Boolean, 返回 ToNumber(x) == y 的結果。
- 如果 Type(y) 爲 Boolean, 返回 x == ToNumber(y) 的結果。
- 如果 Type(x) 爲 String 或者 Number 並且 Type(y) 爲 Object,返回 x == ToPrimitive(y) 的結果。
- 如果 Type(x) 爲 Object 並且 Type(y) 爲 String 或者 Number,返回 ToPrimitive(x) == y 的結果。
- 返回假。
有了這個流程,就可以知道上面提到的幾個式子成立的原理:
[]==false
任意數組轉換爲布爾值時都爲真,但與布爾值進行==
運算操作時,首先會將布爾轉換爲數字,即
false=>0,接着再與數組進行==
運算。這時,需要進行 toPrimitive([],Number)
運算了,返回0,所以式子返回真。
[1]=='1'
數組與字符串比較,直接轉換爲 toPrimitive([1],String)
== '1'
,顯然爲真。
總結
在使用 ==
進行操作之前,一定要明確兩邊值類型所帶來的結果差異,必要時,直接強轉爲布爾值進行計算。
參考