Lodash 源碼導讀 - isNaN 篇

更新於 發佈於 閱讀時間約 8 分鐘
raw-image


完整源碼

撰稿時版本為 v4.17.15

撰稿時版本為 v4.17.15


解析源碼

Line 1 ~ 28 註解部分

此部分為該函式的文件說明,簡單地描述了其用途,傳參型別介面與使用範例等資訊。特別看到第 4 行的 note 直接說明了這個函式與全域下那個遇到 undefined 或其他非數值時會回傳 true 的 isNaN 不同。


Line 30 ~ 32 註解部分

// An `NaN` primitive is the only value that is not equal to itself.

第 30 行註解指出,NaN 是 JavaScript 中唯一一個不等於自身的值。這意味著如果一個值不等於自身,它一定是 NaN。例如:

NaN === NaN // false

請特別注意這個特性,因為這是 Lodash 執行檢測 NaN 的核心原理之一,後續也會反覆提到。


// Perform the `toStringTag` check first to avoid errors with some
// ActiveX objects in IE.

第 31 至 32 行註解解釋了在 IE 瀏覽器中的某些情況下,如果值來自 ActiveX 對象,可能會引發錯誤。因此,Lodash 在檢查 value 是否為 NaN 之前,會先通過 isNumber 來檢查它是否為數值型別,這樣可以避免非數值型別進入後續的判斷,減少潛在的錯誤。


Line 33 函式內容

return isNumber(value) && value != +value

這行源碼包含兩個條件:

  • isNumber(value):確認 value 是否為數值型別。isNumber 是 Lodash 中另一個函式,專門檢查變數是否為數值。
  • value != +value:這是該函式的核心邏輯。它嘗試將 value 強制轉型為數值型態再進行比較,並檢查 value 是否不等於自身。


完整邏輯說明

在該函式中,Lodash 先是檢查 value 的型別,若非數值就直接返回 false。接著進行 NaN 檢查,若 value 是數值且符合 value != +value(也就是不等於自身),則確認為 NaN,返回 true。


前面我們提過 NaN 有一個特性就是它不等於它自己。

NaN compares unequal (via ==, !=, ===, and !==) to any other value — including to another NaN value.

因此 Lodash 利用此特性當 value 是 NaN 時,它會滿足 value != +value 條件。除此之外,任何數值類型(例如 0、1,Infinity 等)都不會滿足這個條件。

const foo = 0
console.log(foo != +foo) // false

const bar = NaN
console.log(bar != +bar) // true


這邊你可能會注意到一個陌生的寫法 +value,它的目的是強制將 value 轉為數值型別。既然使用 isNumber 檢查 value 了,又為什麼要操作轉型別呢?讓我們深入探討其原因。

  • 確保一致的數值運算+value 是一種確保 value 參與數值比較時行為一致的方式。雖然 isNumber 已經確認 value 是數值型別,但在 JavaScript 中,數值型別仍然可能包含特殊的 NaN 或 Infinity。而透過 +value 在數值型別的操作中會保持一致的行為,就算遇到一些極端數值情況(例如 Number('NaN')),也能使運算更具穩定性。
  • 進一步強化 NaN 檢測:在 JavaScript 中,NaN 是唯一一個不等於自身的值,而 value != +value 利用了這個特性。即便有些情況下 value 是數值型別(如來自不同的運算結果或隱式轉換),這個寫法都能確保判斷的結果正確。

回到 Lodash 源碼本身,就目前的函式內容來看,在大多數情境下不寫 + 仍然會得到相同的結果,但其實補上這種寫法會更嚴謹,從而避免某些潛在的轉型錯誤。


實務說明

情境用途

_.isNaN 是 Lodash 函式庫提供的一個 utility,用來檢查數值是否為 NaN。該函式尤其適合用於處理數值陣列或檢查計算結果。當數值經過多次運算而可能出現 NaN 的情況時(例如在資料處理和數據分析中)它能幫助我們有效地檢查和排除無效數值。

這在 JavaScript 開發中非常有用,因為內建的 isNaN 函式存在部分缺陷,特別是在處理非數值類型時。但 Lodash 提供的 _.isNaN 方法能讓這個檢查情境更直觀與安全。


型別定義

declare function isNaN(value: any): boolean;


基本用法

  • 原始 Lodash 版本
const result1 = _.isNaN(NaN) // true
const result2 = _.isNaN(4) // false
const result3 = _.isNaN('hello') // false
const result4 = _.isNaN(undefined) // false
  • nuxt-lodash 版本
// 請注意此處的 isNaN 是 nuxt-lodash 的,而非原生 isNaN

const result1 = isNaN(NaN) // true
const result2 = isNaN(4) // false
const result3 = isNaN('hello') // false
const result4 = isNaN(undefined) // false


另外當你需要過濾掉 NaN 值時,也可以搭配 Lodash 的 _.filter 進行過濾:

const values = [1, NaN, 3, NaN, 5]
const filteredValues = _.filter(values, value => !_.isNaN(value))

console.log(filteredValues) // [1, 3, 5]

與原生 isNaN 的區別

在 JavaScript 原生 isNaN 函式中,非數值(如字串或物件)會被強制轉為數字再進行檢查,這會導致一些誤判。例如:

isNaN('hello') // true,因為 'hello' 轉為數字後結果為 NaN


而 Lodash 的 isNaN 僅在值真的等於 NaN 時才會返回 true,因此它不會受強制轉型的影響。例如:

_.isNaN('hello') // false,因為 'hello' 並非 NaN


總結

Lodash 的 isNaN 函式提供了我們一個簡單而準確的方法來檢查是否為 NaN。

它的重點在於結合 isNumbervalue != +value 的判斷來進行精準檢測,同時避免了 JavaScript 原生 isNaN 的弱點。這種設計讓它能在 JavaScript 各種環境中準確地識別 NaN 且不會受到非數值類型的影響,使得它在開發中更為安全並提升我們程式碼的嚴謹性。


Cheng's murmur

你各位被教召了嗎,我被教召了⋯
avatar-img
2會員
6內容數
生活就是 早上 8 點的文湖線;晚上 8 點的 New York Sour;帶著一台 GR3X 意興闌珊的漫步;嚮往著午後草皮上陪拉布拉多 🐶 玩耍;拿起似有似無的筆開始敲打創作。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~