概要
JavaScriptにおいて最も混乱を招く型のひとつが、null
と undefined
だ。
両者とも「何もないこと」を表すが、その意味と意図はまったく異なる。
誤用すると意図しないバグや、状態管理の不整合を引き起こす。
本記事では、両者の仕様的違いから、状態設計における使い分け戦略までを構造的に解説する。
対象環境
JavaScript(ES5〜ES2023対応)
Node.js / ブラウザ
結論から:違いを一言で言えば
型 | 意味 | 誰が設定するか | 用途 |
---|---|---|---|
undefined |
値が未定義 | JavaScriptエンジン | 初期化されていない変数 |
null |
値が「ない」と明示的に定義 | 開発者(人間) | 意図的に「空」を示したい時 |
undefinedとは何か?
let a;
console.log(a); // undefined
- 初期化されていない変数のデフォルト値
- 存在しないプロパティアクセスも同様
const obj = {};
console.log(obj.key); // undefined
→ 「値が存在しない」ことをJavaScriptエンジンが教えてくれる状態
nullとは何か?
const user = {
name: null
};
- 開発者が明示的に「ここには値がない」と設定した状態
- APIレスポンスなどで「データが空」を表す用途
→ 「空である」ことを“意図して”示すために使う
厳密な型の違い(typeof)
typeof undefined // "undefined"
typeof null // "object" ← 歴史的バグ(仕様としてそのまま)
等価性と比較の挙動
==
(抽象的比較)
null == undefined // true
→ どちらも「値がない」とみなされる
===
(厳密比較)
null === undefined // false
→ ✅ 実務では常に ===
を使うべき
実務での使い分け指針
状態 | 使用する型 | 理由 |
---|---|---|
まだ値が代入されていない | undefined |
JavaScriptが自動で設定 |
意図的に「空」と示す | null |
状態を明示(例:初期値、削除後など) |
関数の返り値が失敗を示す | null |
return null → 値が取得できなかった意図 |
オプション引数の省略 | undefined |
実引数が渡されなかったときの識別 |
APIのレスポンスで「空値」 | null |
仕様的に「無効な値」を明示する必要がある場合 |
実装例:状態設計での分岐
function getUser(id) {
if (!id) return undefined; // 呼び出し側ミス
if (id === 'deleted') return null; // 正しく存在しない
return { name: 'toto' };
}
const user = getUser('deleted');
if (user === undefined) {
console.error('引数エラー');
} else if (user === null) {
console.warn('該当ユーザーなし');
} else {
console.log(user.name);
}
よくあるミスとアンチパターン
❌ undefined
を手動で代入する
user.name = undefined; // ❌ 意図が不明瞭になる
→ ✅ 「意図的に空」とするなら null
を使うべき
❌ == null
を使って2つを一気に判定
if (value == null) {
// null または undefined の場合に入る
}
→ ✅ 厳密に区別すべき場合は === null
または === undefined
JSONとAPI設計における扱い
{
"email": null, // 明示的に「ない」
"phone": undefined // → JSONに含まれない
}
→ undefined
は JSON.stringify で削除される
→ APIに送る値としては nullが明示性に優れる
結語
undefined
は「まだ定義されていない」
null
は「定義はされたが、値が空であると“人が”意図した」
両者の違いはコードの意図と責任の違いである。
- 値が存在しないことに責任がないなら
undefined
- 空であることに責任を持ちたいなら
null
JavaScriptの曖昧さに負けず、自分の意図を明確に持ち、伝えるコードを書くこと。
その小さな選択の積み重ねが、大きな安定を生む。