[Forwarded] A 10-line “Is this a number?” check: how is-number works | [轉] 10 行搞掂「係咪數字」:拆解 is-number 點樣判斷
When you validate user input, you’ll see values like "42", " 3.14 ", or "1e3".
typeof x === 'number' misses numeric strings, while isNaN(x) can be tricked by coercion.
The is-number utility returns true only when the value is either a finite JavaScript number or a non-empty string that can be converted to a finite number.
The code
1
2
3
4
5
6
7
8
9
10
11
module.exports = function(num) {
if (typeof num === 'number') {
return num - num === 0;
}
if (typeof num === 'string' && num.trim() !== '') {
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
}
return false;
};
1) Why num - num === 0?
For finite numbers, n - n is always 0.
But for NaN, and for Infinity - Infinity, the result is NaN—so the comparison fails. This effectively filters out NaN and ±Infinity.
2) Why trim() !== ''?
Without it, +'' and +' ' become 0, which would incorrectly treat blank input as numeric. The trim() guard prevents that.
3) Why +num?
Unary + explicitly converts the operand to a number (similar intent to Number(num)), so strings like " 5 ", "1e3", or even "0x11" can become numbers.
4) Number.isFinite vs global isFinite
- Number.isFinite(x) checks “is x a finite number” without coercion.
- Global isFinite(x) coerces first, which can be surprising.
The fallback exists for older runtimes; +num ensures both paths test the numeric conversion consistently.
做表單/API 入參驗證,你成日會見到:"42"、" 3.14 "、"1e3",甚至 " "。
淨係用 typeof x === 'number' 會漏咗字串數字;用 isNaN(x) 又好易畀型別轉換整蠱。
is-number 呢段做法就係:只要係「有限嘅 number」或者「可轉成有限 number、而且唔係空白嘅字串」先回傳 true。
原始碼
1
2
3
4
5
6
7
8
9
10
11
module.exports = function(num) {
if (typeof num === 'number') {
return num - num === 0;
}
if (typeof num === 'string' && num.trim() !== '') {
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
}
return false;
};
1)點解用 num - num === 0?
正常有限數:n - n 一定係 0。
但 NaN - NaN 仍然係 NaN;Infinity - Infinity 都會變 NaN,所以唔會等於 0——即係自動篩走 NaN 同 ±Infinity。
2)字串分支:trim() 防止「空白當 0」
如果冇 num.trim() !== '',+'' 同 +' ' 都會變 0,咁你輸入空白都會被當成數字。trim() 就係專登擋住呢啲情況。
3)+num 一元加號:顯式轉做數字
一元 + 會嘗試將操作數轉成 number,所以 " 5 "、"1e3"、甚至 "0x11" 都可能轉到數。
所以呢個實作會接受十六進制字串(例如 “0x11”)——佢冇限制「只准十進制」。
4)Number.isFinite 同全域 isFinite 有咩分別?
- Number.isFinite(x):唔做隱式轉型,直接判斷係咪有限 number。
- 全域 isFinite(x):會先轉型再判斷,可能有驚喜(亦可能有驚嚇)。
作者寫兼容分支,係為咗舊環境冇 Number.isFinite 都用得;而 +num 令兩邊都先做同一種數值轉換