【3分鐘速覽】如何「嚴謹地」判斷兩個變量是否相同

引言

如何「嚴謹地」判斷兩個變量相同?僅僅使用 === 就能夠了麼?html

嚴格相等

咱們能夠很是快的寫一個 is 方法來判斷變量 x 是否就是 y:react

// 初版
function is(x, y) {
  return x == y;
}

固然,你會很快發現,方法裏用了 ==,因爲隱式轉換的問題,這並不嚴謹。因此咱們天然會使用以下的方法:git

// 第二版
function is(x, y) {
  return x === y;
}

那麼這是否完美了呢?github

一個「更嚴謹」的方法

// 第三版
function is(x, y) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}

上面方法相較於咱們經常使用的第二版更復雜了。那麼爲何多了這麼多判斷呢?redux

下面讓咱們來詳細看看。編碼

1. Infinity

瞭解 JavaScript 的同窗應該會記得,在全局中有一個叫作 Infinity 的屬性,表示數值上的無窮大。spa

Infinity 屬性的屬性特性
writable false
enumerable false
configurable false

同時,你用 Number.POSITIVE_INFINITY 也能獲取到該值。code

於此對應的,也有個 Number.NEGATIVE_INFINITY 的值,實際就是 -Infinityhtm

Infinity 比較特殊的一點在於,在 JavaScript 中 1 / Infinity-1 / Infinity。 被認爲是相等的(因爲 +0-0,下一節會進一步介紹)blog

而在不少場景中,包括像一些 deepEqual 之類的方法中,咱們不但願將其斷定爲相等。學過統計的同窗都知道假設檢驗中有兩類錯誤

  • I類錯誤:棄真錯誤(false positive)
  • II類錯誤:取僞錯誤(false negative)

結合咱們上面提到的,第一個條件判斷可能就會犯II類錯誤 —— 1 / Infinity-1 / Infinity 不相同,卻判斷爲相同了。因此須要進一步判斷:

x !== 0 || y !== 0 || 1 / x === 1 / y

1 / Infinity-1 / Infinity 在與 0 的相等判斷中都會爲 true

而其倒數 Infinity-Infinity 是不相等的,因此避免了 1 / Infinity-1 / Infinity 的判斷問題。

2. +0-0

其實,上面 Infinity 問題的核心緣由在於於 JavaScript 中存在 +0-0

咱們知道每一個數字都有其對應的二進制編碼形式,所以 +0-0 編碼是有區別的,平時咱們不主動聲明的話,所使用的其實都是 +0,而 JavaScript 爲了咱們的運算能更加方便,也作了不少額外工做。

想要更進一步瞭解 +0-0 能夠讀一下 JavaScript’s two zeros 這篇文章。

但在不少判斷相等的工做上,咱們仍是會把 +0-0 區分開。

x !== 0 || y !== 0 || 1 / x === 1 / y

上面這個式子也就起到了這個做用。

3. NaN

JavaScript 中還有一個叫 NaN 全局屬性,用來表示不是一個數字(Not-A-Number)

NaN 屬性的屬性特性
writable false
enumerable false
configurable false

它有一個特色 —— 本身不等於本身:

這可能會致使判斷出現 I 類錯誤(棄真錯誤):本來是相同的,卻被咱們判斷爲不相同。

解決的方法也很簡單,JavaScript 中只有 NaN 會有「本身不等於本身」的特色。因此只須要判斷兩個變量是否都「本身不等於本身」便可,即都爲 NaN

x !== x && y !== y

若是兩個變量都爲 NaN,那麼他們其實就仍是相同的。

總結

總的來講,咱們的增強版就是額外處理了 +0/-0NaN 的狀況。

實際項目中,不少時候因爲並不會碰這樣的業務值,或者這些邊界狀況的判斷並不影響業務邏輯,因此使用 === 就足夠了。

而在一些開源庫中,因爲須要更加嚴謹,因此不少時候就會考慮使用第三版的這類方法。例如在 react-redux 中對 props 和 state 先後相等性判斷underscore 中的相等判斷方法等。而 underscore 中更進一步還對 nullundefined 作了特殊處理。

相關文章
相關標籤/搜索