【JavaScript】undefinedとは?初心者にもわかりやすく具体例つきで解説
はじめに
JavaScriptを学び始めたときに、undefined という値を見かけることはありませんか。
初心者の方にはややこしく感じるかもしれませんが、この undefined はJavaScriptの特徴を理解するうえでとても重要な存在です。
プログラムで思わぬエラーを引き起こす原因になったり、思った動作をしなかったりする背景には、実は undefined の扱い方に対する誤解があることが少なくありません。
しかし、正しく理解しておけば、undefined をうまく回避したり、想定外の動作を減らしたりすることができます。
ここでは undefined がどういうものなのか、具体的なコード例や実務での活用シーンをまじえながら、初心者でもわかりやすく解説していきます。
この記事を読むとわかること
- undefined の基本的な概念と特徴
- undefined と null の違い
- 関数内やオブジェクトで undefined が発生する具体例
- 実務で気をつけたい undefined の扱い方
- コード例を用いた undefined のチェック方法
JavaScriptにおけるundefinedの基本
JavaScriptでよく見かける undefined は、変数がまだ値を割り当てられていない状態を表す特殊な値です。
ここでは、その基本的な意味や振る舞いを見ていきましょう。
undefinedとは何か
undefined は、変数が宣言されたものの、値が設定されていないときに自動的に割り当てられる値です。
たとえば、次のようなコードを実行すると、変数 x
には何も代入されていないため、undefined
が表示されます。
let x; console.log(x); // undefined
JavaScriptでは、変数が定義されているだけでは初期値が設定されず、undefined となるのがデフォルトです。
なお、独自に値を代入していない限り、undefined はエンジン側が「まだ値を与えられていない」と判断して自動的に付与するものだと考えると理解しやすいでしょう。
変数とundefinedの関係
変数を宣言しただけで値を代入しなかった場合には、undefined が代入されるのがJavaScriptの特徴です。
また、オブジェクトのプロパティにアクセスした場合でも、そのプロパティが存在しないときに undefined が返されます。
const obj = { name: "Alice" }; console.log(obj.age); // undefined (存在しないプロパティにアクセス)
このように、「そこに何も値が用意されていない状態」 を示すのが undefined です。
実務での活用シーン:エラーチェック
たとえば、サーバーから受け取ったデータをオブジェクトとして扱うケースがよくあります。
このとき、オブジェクトの中身をそのまま使おうとすると、プロパティが存在しなかった場合に undefined になり、エラーを引き起こす可能性があります。
このような場面で「もし値が undefined であれば、別の代替処理を行う」という分岐が必要になります。
そのため undefined という値の存在をしっかり把握しておかないと、思わぬエラーに気づかずに困ることになるかもしれません。
undefinedが返される具体的な場面
先ほどは変数に値を代入しない場合や存在しないオブジェクトのプロパティにアクセスする場合に undefined が返ってくると説明しました。
ここではさらに踏み込んで、よくあるケースをいくつか挙げます。
関数の戻り値がないとき
JavaScriptの関数は、戻り値を明示的に return
しなかった場合に undefined を返します。
function greet() { console.log("Hello!"); // returnの記述なし } const result = greet(); // 関数呼び出し console.log(result); // undefined
上記の例では、greet()
関数の中で return
をしていないため、自動的に undefined が返される仕組みになっています。
この性質を知らずに、関数の実行結果をそのまま使おうとしてトラブルになることがよくあります。
関数のパラメータが未指定のとき
JavaScriptでは、関数を呼び出す際に渡す引数が足りなかった場合、その「渡されなかった引数」には undefined が入ります。
次の例を見てみましょう。
function add(a, b) { console.log(a); // 10 console.log(b); // undefined return a + b; } const sum = add(10); // bが指定されていない console.log(sum); // NaN (10 + undefined)
この例では、add(10)
の呼び出し時に第2引数が指定されていないため、b
には undefined が入り、結果的に NaN
(Not a Number)が返されます。
実務では引数が足りなくなるシチュエーションは意外と多く、ライブラリやフレームワークのコードを呼び出すときや、APIからの応答を関数にそのまま渡すときなどに注意が必要です。
delete演算子によるプロパティの削除
オブジェクトのプロパティを delete
演算子で削除した場合、そのプロパティを再び参照すると undefined が返されます。
ただし、このときオブジェクトにプロパティ自体がなくなるため、in
演算子などを使えば完全に削除されたことを検証できます。
const person = { name: "Alice", age: 25 }; delete person.age; console.log(person.age); // undefined console.log("age" in person); // false
このように、一度削除されたプロパティは存在しないのと同じ扱いになるため、undefined という結果になります。
配列の要素が指定されていない
JavaScriptの配列で、要素を意図的に空けてしまう「ホール(欠損要素)」がある場合、そこにも undefined が入りがちです。
また、配列の一部だけを削除するときなどにも似たような状況が生じることがあります。
const arr = [1, , 3]; console.log(arr[1]); // undefined (ホール)
実務的には配列を適切に初期化したほうがトラブルを少なくできますが、「どうしても空を許容したい」「要素が未定の場合は空にしておきたい」という状況では、こうした挙動が起こりうるため注意が必要です。
undefinedとnullの違い
JavaScriptには undefined と null の2つの「値がない」ことを示すデータがあります。
しかし、この2つは意味合いが異なります。
nullは「意図的な空」
null は、「ここに値が存在しないことを、開発者が意図的に示したい」という場合に使うのが基本的な考え方です。
一方で undefined は、「まだ値がセットされていない(もしくは存在しない)」ことを示します。
実務では「値がない」ことを示す場合、null を使って明示的に「ここには値がない」という意図を表すことが多いです。
一方、undefined はプログラム内部の処理や宣言だけ行われて実体がない場合に自動的に付与されることが多いです。
具体的なコード例
次の例では、myVar
に null を代入し、anotherVar
は宣言のみをしています。
それぞれをコンソールに出力すると、次のような結果になります。
let myVar = null; let anotherVar; console.log(myVar); // null console.log(anotherVar); // undefined
開発者が「ここは明示的に空です」と示すために null を使うのに対し、「単にまだ値が設定されていない状態」だとJavaScriptが判断するときには undefined が使われる、と考えてみてください。
nullとundefinedを混同するリスク
もし開発者が「意図的に値を空にしたい」つもりで null を代入したはずが、知らないうちに undefined が混ざっていたとしたら、バグの原因になります。
また、条件分岐で null と undefined を分けて扱いたいのに、まとめて「falsy」扱いしていると気づかずにロジックが破綻するケースもあります。
そのため、どのような場面で null を使用し、どのような場面で undefined が自然に発生するかを理解しておくことが、プログラミングの安定動作につながります。
undefinedの判定方法
JavaScriptでは、値が undefined かどうかをチェックする方法がいくつかあります。
実務では条件分岐で「undefined じゃないならこの処理をする」というロジックを書く場面が頻繁にありますので、代表的な判定方法を押さえておきましょう。
typeof演算子を使う
typeof
演算子は、JavaScriptの値がどのような型かを文字列として返すものです。
undefined の場合、次のように "undefined"
が返されます。
let value; if (typeof value === "undefined") { console.log("valueはundefinedです。"); }
ここで注意したいのは、typeof
はオブジェクトや関数などに対してもユニークな文字列を返すため、undefined と区別しやすいという点です。
ただし、オブジェクトや配列などでも「typeof
では 'object' になる」という現象があるため、さらに厳密なチェックが必要になることもあります。
厳密等価演算子(===)を使う
JavaScriptには「厳密等価演算子」という ===
が存在します。
==
(ゆるい等価演算子)と異なり、型変換を行わずに比較するため、undefined をチェックするときに重宝します。
let value; if (value === undefined) { console.log("valueはundefinedです。"); }
value === undefined
とすることで、型まで含めて一致しているかどうかを確認します。
これにより、null
と undefined を区別したり、予期せぬ自動型変換を回避したりできるため、実務ではこちらのほうが好まれることが多いです。
optional chainingやnull合体演算子との組み合わせ
近年では、オブジェクトや変数にアクセスするときに undefined を返してしまうリスクを小さくする文法として、オプショナルチェーン演算子(?.
)やnull合体演算子(??
)が使われるようになってきています。
たとえば、次のように書けば、someProperty
が存在しない場合に undefined ではなく "default"
を返すことができます。
const obj = { name: "Alice" }; const result = obj.someProperty ?? "default"; console.log(result); // "default"
また、オブジェクトのプロパティにアクセスするときも、オプショナルチェーン演算子を使って undefined を返すのを回避するか、あるいは安全に扱うことができます。
const user = { name: "Bob", address: { city: "Tokyo" } }; // addressが存在しない可能性を想定 const cityName = user.address?.city ?? "Unknown"; console.log(cityName); // "Tokyo"
このような演算子を組み合わせることで、undefined を引き金とするエラーを減らすことが可能です。
実務での注意点とトラブルシューティング
ここでは、実際の開発現場で undefined が原因で起こりうるトラブルと、その対応方法をいくつかピックアップします。
エラーの根本原因をログで追う
「変数や関数の戻り値が想定していないタイミングで undefined になっている」ときには、まずコンソールログを細かく埋め込み、どこで undefined が入り込んでいるのかを調査します。
以下のように console.log()
で実行箇所や変数の値を確認し、問題の箇所を特定すると早いです。
function processData(data) { console.log("[processData] data:", data); if (!data) { console.log("dataがundefinedまたはnull、もしくはfalsyです。"); return; } // dataが正常に存在している場合の処理... }
このようなトラブルシューティングを地道に行うことで、「想定外の undefined」がどこで発生しているのかを解き明かすことができます。
オブジェクトの構造が変更された場合
大規模開発では、APIの仕様変更や、データ構造が変わった結果、今まで存在していたプロパティがなくなることもあります。
そうすると、呼び出し元では存在しているはずのプロパティを参照しようとして undefined に悩まされるケースが出てきます。
こうしたトラブルを回避するためには、受け取るデータの構造を常に最新の状態で把握し、必要に応じてオプショナルチェーンを使ったり、存在しないプロパティにアクセスしたときのフォールバック(代替値)を実装したりします。
関数の引数を想定より多く/少なく渡した場合
先ほど例に挙げたように、JavaScriptは関数の引数が足りなくてもエラーにならず、結果的に undefined を受け取ります。
逆に言えば、余分な引数を渡しても自動的に無視される仕組みがあります。
これを理解していないと、「関数が意図したとおりに動かない」「第2引数を当たり前に使うつもりだったのに undefined になってしまう」といった問題が出てきます。
複数の開発者が関わる場合は、関数に期待する引数の数をコメントやドキュメントに明示しておくとよいでしょう。
APIレスポンスが想定外の場合
REST APIやGraphQLなど、外部サービスからデータを受け取る際に、レスポンスがそもそも想定していた形で返ってこないことがしばしばあります。
こういったケースでも、プロパティを参照したときに undefined が返ってくる可能性が高まります。
実務では、APIレスポンスを受け取ったら必ずバリデーション(形式チェック)を行い、undefined が含まれないかを確認します。
これにより、バグの早期発見だけでなく、アプリケーションの安定稼働につなげることができます。
具体的なコード例:undefinedを安全に扱う
ここからは、いくつかの実用的なコード例を挙げながら、undefined を安全に扱う方法をもう少し詳しく紹介します。
例1: デフォルト値を使う
引数にデフォルト値を指定しておくと、呼び出し元で引数を渡さなかった場合でも、undefined が入ることを回避できます。
function greetUser(name = "Guest") { console.log(`Hello, ${name}!`); } greetUser(); // Hello, Guest! greetUser("Charlie"); // Hello, Charlie!
このようにすると、名前を指定しなくても "Guest"
がデフォルトで使われるため、undefined のまま処理が進むことはありません。
例2: 早期リターンでエラー回避
関数の冒頭で、必要な引数が存在するかどうかをチェックし、なければ早期にリターンする手法はよく使われます。
function processData(data) { if (data === undefined) { console.log("必要なデータがありません。"); return; } // dataがあることが保証される処理 console.log("データが存在するので処理を続行します。"); }
これにより、先にエラーを検出して処理を中断できるため、undefined による後続の処理エラーを防ぎます。
例3: オプショナルチェーンで安全にアクセス
オブジェクトや配列の深い階層にアクセスするときに、途中のプロパティが存在しないとundefined になり、そこでエラーが起きる可能性があります。
オプショナルチェーン(?.
)を使うと、プロパティが存在しない場合にエラーではなく undefined を返し、さらにnull合体演算子(??
)と組み合わせると別の値で補うことができます。
const user = { name: "Dave", address: { city: "Osaka" } }; const cityName = user.address?.city ?? "Unknown City"; console.log(cityName); // "Osaka" const phoneNumber = user.contact?.phone ?? "No phone number"; console.log(phoneNumber); // "No phone number"
実務では、APIから受け取ったデータを扱う際などに極めて有用な書き方です。
よくある誤解とアンチパターン
undefined にまつわる典型的な誤解や避けたいパターンも知っておくと、コードの保守性が向上します。
誤解1: undefinedを自分で代入してしまう
JavaScriptでは、変数に直接 undefined を割り当てること自体は可能です。
しかし、これは混乱を招く原因になるため、基本的には推奨されません。
let sample = undefined; // あえて代入するのは避ける
代わりに、「値がない」ことを明示したい場合は null を使うほうが意図が明確になります。
誤解2: 全てのエラーをtry-catchで囲む
undefined が原因でエラーが起きるかもしれないからといって、コード全体を try-catch
で囲むのは好ましくありません。
本来ならば条件分岐やオプショナルチェーンを活用して、undefined を想定した設計にするのが基本です。
誤解3: == でundefinedをnullと一括判定
==
は型変換を伴う比較のため、undefined と null は同じ「falsy」値として扱われる場合があります。
そのため、次のような比較は混乱を招きます。
if (myVar == null) { // myVarがundefinedでもtrueになる }
実務では、===
を使うか、オプショナルチェーンやnull合体演算子を組み合わせた明示的な書き方で回避しましょう。
トラブルを減らすためのポイント
ここでは、undefined に振り回されないための実務的なポイントをまとめます。
コーディング規約でnullとundefinedの使い分けを明確に
プロジェクト内で、「意図的に値がないときは null を使う」「未設定の場合は自動的に undefined が入る」といったルールを決めておくと、混乱が減ります。
開発メンバー間で統一した運用をすることが大切です。
オプショナルチェーン演算子の積極的活用
ネストが深いオブジェクトを扱うときには、オプショナルチェーンとnull合体演算子の組み合わせを積極的に導入することで、undefined によるエラーを大幅に減らすことができます。
これは見た目の読みやすさにも寄与するため、多くの開発現場で採用されています。
テストコードでundefinedへの耐性をチェック
単体テストや結合テストの中で、「引数が渡されなかったらどうなるのか」「APIレスポンスが空の場合はどうなるのか」を確認するテストケースを用意しておくと、バグを早期に検出できます。
undefined はJavaScriptが自動的に代入する値であるため、テストの見落としをしないように気をつけましょう。
テストコードを書くときには、普段ありえないと思っているケースもフォローすることで、思わぬバグを減らせます。
undefinedを使いこなすメリット
少し遠回りに感じるかもしれませんが、undefined の概念をしっかり理解しておくと、次のようなメリットがあります。
- 「値がない状態」と「値はあるけれど指定されていない状態」の違いをコードで表現できる
- バグ発生時に、undefined なのか null なのかで原因を切り分けやすくなる
- 余計な
try-catch
や無駄な条件分岐を減らし、コードの見通しがよくなる
このように、undefined の適切な扱い方を身につけることは、JavaScript全体を理解する上で大きなアドバンテージになります。
実務でおすすめの書き方や事例
プロジェクトによっては、開発メンバー全員が同じコーディングパターンを採用するルールがあります。
以下は、実務でよく見られる書き方のパターン例です。
引数が足りない場合のデフォルト値
先述した「デフォルト引数」の応用として、引数が足りない場合にはすぐに関数を終了させるパターンもあります。
function saveUserData(user) { if (!user) { console.log("userが未定義なので処理を終了します。"); return; } // userが正しく存在するときの処理... }
こうすることで、undefined を無理に処理しようとせず、早期に呼び出し元へ戻せます。
複数のAPIレスポンスをまとめてチェック
複数のAPIを順番に呼び出し、その結果をまとめてオブジェクトに収納するケースがあります。
このとき、「各レスポンスが undefined だった場合はエラーを投げる」あるいは「デフォルト値で補う」といった一括処理を行うと便利です。
async function fetchAllData() { const [data1, data2, data3] = await Promise.all([ fetchData1(), fetchData2(), fetchData3() ]); if (!data1 || !data2 || !data3) { throw new Error("必要なデータが取得できませんでした。"); } return { data1, data2, data3 }; }
このように処理をまとめると、思わぬ undefined が紛れたときでも素早く対処できます。
明示的にチェックすることで、undefinedのまま先に進んでしまうリスクを減らせます。
まとめ
JavaScriptの undefined は、初学者にとってわかりにくい概念の一つかもしれません。
しかし、その本質は「まだ値が割り当てられていない状態」を表すシンプルなものです。
- 変数を宣言しただけだと undefined が入る
- 関数で
return
しなければ undefined が返る - オブジェクトの存在しないプロパティを参照すれば undefined になる
- null は明示的な「空」であり、undefined とは使い分ける
- 条件分岐には
===
を使うか、オプショナルチェーンやnull合体演算子を活用する
こうしたポイントを押さえておけば、実務で意味不明なエラーに悩まされる場面が減るでしょう。
undefined をしっかり理解しておくことは、JavaScriptプログラミングの基盤を固める上で重要です。
JavaScriptを使った開発では、どんなに簡単なプログラムであっても、undefined が原因のバグは発生しがちです。
そのため、今回紹介したポイントやコード例を参考に、ぜひ undefined をうまくコントロールしてみてください。
慣れてくると、undefined が起こりうる箇所を事前に想定できるようになり、バグの予防策を自然に取り入れられるようになります。
これからJavaScriptを本格的に学習する方にとっても、undefined の理解は大切な第一歩です。
自分のコードで「なぜか値が取得できない」「思ったとおりの結果にならない」と感じたときは、今回の内容を思い出し、undefined の可能性を真っ先に疑ってみてください。