Javascript "==" 運算符原理

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

  1. 如果 Type(x) 不同於 Type(y), 執行第 14 步。
  2. 如果 Type(x) 爲 Undefined, 返回真。
  3. 如果 Type(x) 爲 Null, 返回真。
  4. 如果 Type(x) 不是 Number, 執行第 11 步。
  5. 如果 x 爲 NaN, 返回假。
  6. 如果 y 爲 NaN, 返回假。
  7. 如果 x 與 y 有相同的值, 返回真。
  8. 如果 x 爲 +0 並且 y 爲 −0, 返回真。
  9. 如果 x 爲 −0 並且 y 爲 +0, 返回真。
  10. 返回假。
  11. 如果 Type(x) 爲 String, 那麼如果 x 和 y 具有相同的字符序列(等長並且對應位置字符相同)返回真,否則,返回假。
  12. 如果 Type(x) 爲 Boolean, 如果 x 和 y 都是真或者都是假則返回真,否則,返回假。
  13. 如果x和y引用相同的對象返回真,否則, 返回假。
  14. 如果 x 爲 null 並且 y 爲 undefined, 返回真。
  15. 如果 x 爲 undefined 並且 y 爲 null, 返回真。
  16. 如果 Type(x) 爲 Number 並且 Type(y) 爲 String,返回 x == ToNumber(y) 的結果。
  17. 如果 Type(x) 爲 String 並且 Type(y) 爲 Number,返回 ToNumber(x) == y 的結果。
  18. 如果 Type(x) 爲 Boolean, 返回 ToNumber(x) == y 的結果。
  19. 如果 Type(y) 爲 Boolean, 返回 x == ToNumber(y) 的結果。
  20. 如果 Type(x) 爲 String 或者 Number 並且 Type(y) 爲 Object,返回 x == ToPrimitive(y) 的結果。
  21. 如果 Type(x) 爲 Object 並且 Type(y) 爲 String 或者 Number,返回 ToPrimitive(x) == y 的結果。
  22. 返回假。

有了這個流程,就可以知道上面提到的幾個式子成立的原理:

[]==false

任意數組轉換爲布爾值時都爲真,但與布爾值進行== 運算操作時,首先會將布爾轉換爲數字,即 false=>0,接着再與數組進行== 運算。這時,需要進行 toPrimitive([],Number) 運算了,返回0,所以式子返回真。

[1]=='1'

數組與字符串比較,直接轉換爲 toPrimitive([1],String) == '1',顯然爲真。

總結

在使用 == 進行操作之前,一定要明確兩邊值類型所帶來的結果差異,必要時,直接強轉爲布爾值進行計算。

參考


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章