JavaScriptを触り始めて、ふと現れる「数字の判定」。
「あ、これちゃんと数字だな」と思って条件分岐を書いたはずなのに、なぜかバグる……。そんな経験、ありませんか?
大丈夫ですよ、それはあなたが JavaScript に嫌われているわけでも、プログラミングの才能がないわけでもありません。JavaScriptという言語の、ちょっとお節介で気まぐれな性格(仕様)のせいです。
今回は、JavaScriptの泥臭い部分を知り尽くしたアーキテクチャの視点から、誰もが一度はハマる「`isFinite` と `Number.isFinite` の違い」について、お買い物のレジでのやり取りに例えて優しく、そして深く紐解いていきましょう。
—
そもそも「有限な数字」ってなに?
プログラムの世界でいう「有限(finite)」とは、「ちゃんと決まった常識的な範囲の数字」のことです。
例えば、「100」や「3.14」は有限です。でも、無限に続く「Infinity(無限大)」や、数字じゃない「NaN(Not a Number)」は、いわば「計算不能なトラブルメーカー」です。
私たちはプログラムの中で、「今手元にあるデータは、ちゃんと計算できる普通の数字かな?」と確認するために、この「有限かどうか」を調べたいわけです。
そこで登場するのが、判定役の2つのメソッドです。
1. グローバルな `isFinite()` (お節介なベテラン店員)
2. `Number`の `Number.isFinite()` (几帳面な若手スタッフ)
この2人の判断基準の違いを見ていきましょう。
—
1. グローバルな `isFinite()` は「お節介なベテラン店員」
まずは、昔からJavaScriptにいる `isFinite()`(グローバル関数)のお話です。
この人は、とってもお節介です。あなたが「文字」を渡したとしても、
「おっ、これ数字に直せる形じゃん! きっと数字にしたいんだな、よし、俺が代わりに数字にしてから調べてやるよ!」
と、勝手に裏で型変換(暗黙の型変換)を行ってしまいます。
お買い物でのイメージ
お会計のレジに、あなたが「リンゴが3個入った袋」を置いたとします。
ベテラン店員さんは、「あ、これ中身を取り出せば『3』という数字になるな!」と気を利かせて、勝手に袋を開けて「よし、数字としてOK!」と通してしまうようなイメージです。
コードで見てみよう
実際にコードを書いてみると、そのお節介ぶりがよく分かります。
// 数字の「123」はもちろん有限なので true
console.log(isFinite(123)); // ➔ true
// 文字列の「”123″」を渡してみる
console.log(isFinite(“123″));
// ➔ なんと「true」になる!
// (”123” という文字列が、自動的に数値の 123 に変換されてから判定されたため)
// もっとびっくりな例:なんと「空っぽの文字」や「真偽値」も…?
console.log(isFinite(“”)); // ➔ true (空文字は 0 に変換される)
console.log(isFinite(true)); // ➔ true (true は 1 に変換される)
「えっ、文字列を渡したのに `true` になるの!?」と、ここで初心者の多くが混乱してつまずきます。そう、グローバルな `isFinite()` は、「数字じゃないもの(文字列など)を渡されても、一度数字に変換できるか試してから判定する」という性質を持っているのです。
—
2. `Number.isFinite()` は「几帳面な若手スタッフ」
一方で、後からJavaScriptに追加された現代っ子、`Number.isFinite()` は全く違います。
この人は極めて几帳面です。他人の勝手な善意(暗黙の型変換)を一切信じません。
「いや、あなたが渡したのは『文字列』ですよね? 私は数字以外は認めません。たとえ数字っぽく見えても、型が文字なら即アウト(false)です」
と、非常に厳格にチェックします。
お買い物でのイメージ
同じレジでも、几帳面なスタッフさんはマニュアル通りに対応します。
「リンゴの形をしていても、それは『袋(文字列)』という別のデータです。ルール通り、純粋な『数字』でなければ受け付けません!」と、冷たく(しかし正確に)はじき返します。
コードで見てみよう
// 本物の数字ならもちろん true
console.log(Number.isFinite(123)); // ➔ true
// 文字列の「”123″」を渡してみる
console.log(Number.isFinite(“123”));
// ➔ 「false」になる!
// (型が文字列なので、中身が何であれ「数字ではない」と厳しく判定される)
// 空文字や真偽値なんて論外です
console.log(Number.isFinite(“”)); // ➔ false
console.log(Number.isFinite(true)); // ➔ false
素晴らしいですね!「数字を調べたいんだから、文字が来たら `false` になってほしい!」という私たちの直感に、完璧に寄り添ってくれるのがこの `Number.isFinite()` です。
—
比較まとめ:どっちを使うべき?
ここで、2人の判定の違いを一覧表のように整理してみましょう。
| 渡したデータ | `isFinite()` (お節介) | `Number.isFinite()` (几帳面) |
| :— | :— | :— |
| `123` (数値) | `true` | `true` |
| `”123″` (文字列) | `true` (勝手に数値化する) | `false` (厳格に弾く) |
| `””` (空文字) | `true` (`0` に化ける) | `false` |
| `true` (真偽値) | `true` (`1` に化ける) | `false` |
| `Infinity` (無限) | `false` | `false` |
| `”Hello”` (非数字文字) | `false` | `false` |
現場からのアドバイス
実務の現場やWeb制作のフォームバリデーション(入力チェック)などで、もし「ユーザーが入力した値が、純粋な数字かどうか」を調べたい場合、グローバルな `isFinite()` を使うのは危険です。予期せぬ自動変換のせいで、バグの温床になりがちだからです。
基本的には、迷わず几帳面な `Number.isFinite()` を使うことを強くおすすめします。
JavaScriptは歴史の長い言語なので、こうした「似ているけれど挙動が違う関数」がいくつも存在します。でも、その裏にある理由(「後方互換性のために古い仕様を残しつつ、安全な新しい仕様を追加した」という歴史的な経緯)が分かると、なんだか少し愛らしく思えてきませんか?
つまずいたときは、いつでもこの記事を思い出してくださいね。あなたのコーディングライフを、心から応援しています!

コメント