undefinedとは? ― JavaScriptの「未定義」を正しく理解する
undefinedとは、JavaScriptにおいて「値がまだ割り当てられていない」ことを示すプリミティブ値です。変数を宣言しただけで値を代入していない場合や、存在しないオブジェクトのプロパティにアクセスした場合に返されます。
日常生活で例えると、undefinedは「空の引き出し」に近い概念です。引き出し(変数)は存在するけれど、中にはまだ何も入っていない状態です。引き出し自体がない(変数が宣言されていない)のとは異なり、「存在するが中身が未定」という状態を表します。
undefinedが発生する5つの典型的なパターン
パターン1:値を代入していない変数
let やvar で変数を宣言しただけの場合、初期値として自動的にundefinedが割り当てられます。let name; と宣言すると、nameの値はundefinedです。
パターン2:存在しないオブジェクトのプロパティ
const user = { name: "太郎" }; に対して user.age にアクセスすると、ageプロパティは定義されていないためundefinedが返ります。エラーにはならない点がポイントです。
パターン3:関数の引数が渡されなかった場合
関数の仮引数に対応する実引数が渡されなかった場合、そのパラメータはundefinedになります。function greet(name) { ... } を greet() と引数なしで呼ぶと、nameはundefinedです。
パターン4:returnを省略した関数
関数がreturn文を持たない場合、または return; だけの場合、関数の戻り値はundefinedになります。
パターン5:配列の範囲外アクセス
const arr = [1, 2, 3]; に対して arr[10] にアクセスすると、undefinedが返ります。
undefinedとnullの違い ― 最も混同されやすい2つの値
JavaScriptの初学者が最も混乱するのが、undefinedとnullの違いです。
| 比較項目 | undefined | null |
|---|---|---|
| 意味 | 値が「まだ定義されていない」 | 値が「意図的に空である」 |
| 発生 | JavaScriptエンジンが自動的に割り当てる | 開発者が明示的に代入する |
| typeof演算子 | “undefined” を返す | “object” を返す(歴史的な仕様バグ) |
| JSON変換 | JSON.stringify で省略される | JSON.stringify で null として出力される |
| 数値変換 | NaN になる | 0 になる |
簡潔に言えば、undefinedは「システムが設定した未定義」、nullは「開発者が意図した空」です。コードの意図を明確にするため、変数を明示的に空にしたい場合はnullを使い、undefinedを直接代入することは避けるのがベストプラクティスです。
undefinedの判定方法 ― 正しいやり方と危険なやり方
推奨:厳密等価演算子(===)を使う
if (value === undefined) が最も安全で明確な方法です。型の暗黙変換が起こらないため、意図しないマッチを防げます。
推奨:typeof演算子を使う
if (typeof value === "undefined") は、変数が宣言すらされていない場合でもReferenceErrorを起こさず安全に判定できます。
注意が必要:等価演算子(==)を使う場合
value == undefined はnullとundefinedの両方にマッチします。これは「nullもundefinedも同じ『空』として扱いたい」場合には便利ですが、区別が必要な場面では使うべきではありません。
非推奨:真偽値として直接評価する
if (!value) はundefinedをfalseとして扱いますが、0、空文字列、NaN、falseもすべてfalsyです。「0は有効な値だが、undefinedは無効」というケースで誤判定を引き起こします。
モダンJavaScriptでundefinedを安全に扱うテクニック
デフォルト引数(ES6+)
関数パラメータにデフォルト値を設定することで、undefinedが渡された場合のフォールバックを簡潔に記述できます。function greet(name = "ゲスト") { ... }
オプショナルチェイニング(ES2020)
user?.address?.city のように ?. を使うと、途中のプロパティがundefinedやnullの場合にエラーを起こさずundefinedを返します。深いネストのオブジェクトを安全にたどるのに不可欠な構文です。
Null合体演算子(ES2020)
const name = user.name ?? "デフォルト名" は、左辺がnullまたはundefinedの場合のみ右辺を使います。論理OR(||)と異なり、0や空文字列はfallbackされません。
分割代入のデフォルト値
const { name = "不明", age = 0 } = user; のように、分割代入時にデフォルト値を指定できます。
TypeScriptでのundefined対策
TypeScriptを使う場合、コンパイラのstrictNullChecksオプションを有効にすることで、undefinedの可能性がある値を安全に処理することを強制できます。型レベルで「この変数はundefinedかもしれない」ことが明示され、undefinedチェックなしにプロパティにアクセスするコードはコンパイルエラーになります。
よくある質問(FAQ)
Q. void 0 とは何ですか?
A. void 0 は常にundefinedを返す式です。古いJavaScript環境ではグローバルのundefinedが上書き可能だったため、安全にundefinedを得る方法としてvoid 0が使われました。現代のES5以降ではundefinedは書き換え不可になったため、通常は不要です。
Q. undefinedを変数に代入してもいいですか?
A. 技術的には可能ですが、非推奨です。「値を空にしたい」場合はnullを使うのが慣習です。undefinedは「まだ値が設定されていない」というシステム的な状態を表すべきです。
Q. undefinedとReferenceErrorの違いは?
A. undefinedは「宣言済みだが値が未設定」の状態、ReferenceErrorは「そもそも変数が宣言されていない」場合に発生するエラーです。let x; の後に x を参照するとundefined、宣言なしに y を参照するとReferenceErrorです。
まとめ
undefinedはJavaScriptの基本的な値でありながら、正しく理解していないとバグの温床になります。nullとの使い分け、安全な判定方法、モダンな構文(オプショナルチェイニング、Null合体演算子)の活用が、堅牢なコードを書くための鍵です。TypeScriptのstrictNullChecksと組み合わせれば、undefinedに起因する実行時エラーの大部分をコンパイル時に防ぐことができます。

コメント