概要
JavaScriptには「値が存在しないこと」を示すための複数の記号的型がある:
-
undefined
→ 「値が代入されていない」 -
null
→ 「値が明示的に空である」 -
NaN
→ 「数値であるが、結果が不定」
これらを混同すると、以下のような不具合を引き起こす:
- 比較式の誤作動
- 計算結果の伝播的エラー
- UI上の「消えない」表示バグ
- APIレスポンス処理の誤解釈
本記事では、それぞれの意味と設計的に安全な使い方を徹底的に解説する。
1. undefined
:定義されていない(システムによる自動代入)
let a;
console.log(a); // undefined
- 変数は宣言されたが、まだ代入されていない状態
- 関数が
return
しなかったときの戻り値 - 存在しないオブジェクトプロパティのアクセス結果
2. null
:意図的な「空」の意味を持つ設計的な値
let result = null; // 意図的に“なし”を代入
- 明示的に「値が存在しないこと」を表す
- 通常、設計者が「まだ存在しないが、存在し得る」ことを示す
3. NaN
:数値演算の失敗を示す非数値
const n = Number('abc');
console.log(n); // NaN
-
typeof NaN === 'number'
→ ❗ 数値型だが「値がない」 - 自分自身と等しくない唯一の値 →
NaN !== NaN
4. 判定の落とし穴
❌ == による曖昧な比較
null == undefined; // ✅ true(曖昧)
null === undefined; // ❌ false(厳密比較)
→ ✅ 必ず ===
を使用すべき
NaN
の正しい判定法
Number.isNaN(NaN); // ✅ true
NaN === NaN; // ❌ false
isNaN('abc'); // ❌ true → Number('abc')がNaNだから
→ ✅ Number.isNaN()
を使うことで誤判定を避ける
5. 初期化設計の指針
値 | 使うべきケース |
---|---|
undefined |
変数の未初期化、存在しないプロパティ(デフォルト) |
null |
明示的に“値がない”ことを表す。APIレスポンスなど |
NaN |
計算エラーの検知用 → 直接代入は避けるべき |
6. 安全な存在判定の設計
function isPresent(value) {
return value !== null && value !== undefined;
}
if (isPresent(user.name)) {
// 安全に利用可能
}
→ ✅ 0
, ''
, false
などの値は“存在している”とみなすため、== null
ではなく明示的にチェックする
7. デフォルト値の防御的設計
function greet(name) {
const safeName = name ?? 'Guest'; // null / undefined のみを対象
return `Hello, ${safeName}`;
}
- ✅
??
(nullish coalescing)はnull
/undefined
のみ対象 - ❌
||
は''
,0
,false
も対象にするため危険
8. 関数戻り値における初期化設計
function getConfig() {
return null; // ✅ 値がないが存在し得るという“意図”を伝える
}
→ ✅ undefined
は「想定されていない未定義」
→ ✅ null
は「設計上定義された欠損」
設計判断フロー
① “初期化されていない” → undefined(自動で入る)
② “意図的に空”にしたい → null
③ 数値計算で失敗した → NaN(処理で発生、直接使わない)
④ 存在判定したい → !== null && !== undefined
⑤ デフォルト値を設定したい → ?? を使う(|| は非推奨)
よくあるバグ例と対策
❌ if (value)
判定に頼る
if (value) // ❌ false, 0, '', null, undefined 全て落ちる
→ ✅ 存在だけを見たいなら value != null
or value !== undefined
❌ NaNの判定に ==
を使う
if (n == NaN) // ❌ false
→ ✅ Number.isNaN(n)
結語
JavaScriptにおける null
/ undefined
/ NaN
は、すべて「不在の値」を意味するが、
その意味と使い道は設計レベルで明確に区別すべき概念である。
-
undefined
→ 未定義の“発生” -
null
→ 空の“意図” -
NaN
→ 不定の“結果”
不在には意味がある。
それを“意図として設計に刻む”ことが、バグを予防し、読みやすさを高める第一歩である。