閉じる

JavaScriptのnullとundefinedの違いとは?役割の差とエンジニアが意識すべき使い分けを解説

JavaScriptを学んでいると、必ずと言っていいほど「値がない」状態を表す2つの概念、nullundefinedに遭遇します。

一見するとどちらも同じように見えますが、言語仕様上の役割やエンジニアが意図すべき使い分けのルールは明確に異なります。

本記事では、モダンな開発環境において、これらをどのように正しく扱い、バグの少ないコードを書くべきかを詳しく解説していきます。

初心者の方はもちろん、なんとなく使い分けている中級者の方も、改めて基礎を固める材料として活用してください。

undefinedの定義と発生条件

undefinedは、JavaScriptにおいて「変数が定義されているが、値が割り当てられていない状態」を指します。

これはJavaScriptの言語エンジンが自動的に付与する値であるという側面が強いのが特徴です。

変数の初期化忘れ

letvarを使用して変数を宣言し、値を代入しなかった場合、その変数の初期値は自動的にundefinedになります。

JavaScript
let user;
console.log(user); // 初期化されていないためundefined
実行結果
undefined

関数の戻り値

関数内でreturn文が記述されていない場合、またはreturnの後に値が指定されていない場合、その関数はundefinedを返します。

JavaScript
function greet() {
  console.log("こんにちは");
  // return文がない
}

const result = greet();
console.log(result);
実行結果
こんにちは
undefined

存在しないプロパティへのアクセス

オブジェクトの中に存在しないプロパティに対してアクセスを試みた際にも、エラーではなくundefinedが返されます。

JavaScript
const member = { name: "田中" };
console.log(member.age); // ageプロパティは存在しない
実行結果
undefined

nullの定義と役割

対してnullは、「値が存在しないことを明示的に示す」ために使用される特殊な値です。

undefinedがシステム側で自然に発生するものであるのに対し、nullは開発者が意図的に「ここは空である」と定義する際に利用されます。

意図的なリセット

例えば、以前は値が入っていたプロパティを空の状態に戻したい場合、nullを代入するのが一般的です。

JavaScript
let activeSession = { id: 101 };
// セッションを終了させるために意図的に空にする
activeSession = null;
console.log(activeSession);
実行結果
null

APIレスポンスにおけるnull

データベースから取得したデータにおいて、該当する項目が「未入力」であることを示す場合にも、JSONデータとしてnullが返されることがよくあります。

これは「データ構造としては存在するが、中身は空である」という意図を明確にするためです。

nullとundefinedの決定的な違い

これら2つの値には、型や計算時の挙動においていくつかの重要な違いがあります。

以下の表で、主要な差異を整理してみましょう。

比較項目undefinednull
意味未定義(値が割り当てられていない)欠如(値が空であることを明示)
データの型 (typeof)“undefined”“object”
数値変換時の値NaN0
JSONでの扱いキーごと削除されることがある値として保持される

typeof演算子における注意点

JavaScriptの歴史的な仕様により、typeof nullを実行すると“object”が返されるというバグに近い挙動があります。

これはJavaScriptの初期設計におけるミスとされていますが、互換性の観点から現在も修正されていません。

JavaScript
console.log(typeof undefined);
console.log(typeof null);
実行結果
"undefined"
"object"

等価演算子(==)と厳密等価演算子(===)

nullundefinedを比較する場合、使用する演算子によって結果が変わります。

JavaScript
console.log(null == undefined);  // 抽象的な比較では等しいとみなされる
console.log(null === undefined); // 厳密には型が異なるためfalse
実行結果
true
false

実務では、意図しない挙動を防ぐために===を用いた厳密なチェックを行うことが推奨されます。

数値計算における挙動の違い

算術演算にこれらの値が紛れ込んだ場合、結果は大きく異なります。

nullは数値コンテキストでは0として扱われますが、undefinedNaN(Not a Number)に変換されます。

JavaScript
const score = 10;

console.log(score + null);      // 10 + 0 = 10
console.log(score + undefined); // 10 + NaN = NaN
実行結果
10
NaN

この挙動の違いが原因で、計算処理においてバグが発生しやすいため注意が必要です。

モダンJavaScriptでの便利な扱い方

近年のJavaScript(ES2020以降)では、nullundefinedをより安全に扱うための演算子が導入されています。

これらを活用することで、コードの可読性と堅牢性が飛躍的に向上します。

Null結合演算子 (??)

??演算子は、左辺がnullまたはundefinedの場合のみ、右辺の値を返します。

空文字(””)や数値の0を有効な値として保持したい場合に非常に便利です。

JavaScript
const config = {
  timeout: 0,
  theme: null
};

// || 演算子だと 0 が falsy なので 3000 になってしまう
const timeout = config.timeout ?? 3000;
// theme は null なので "light" が採用される
const theme = config.theme ?? "light";

console.log(timeout);
console.log(theme);
実行結果
0
"light"

オプショナルチェイニング (?.)

ネストされたオブジェクトのプロパティにアクセスする際、途中の要素がnullまたはundefinedであってもエラーを投げずにundefinedを返してくれる機能です。

JavaScript
const response = {
  data: {
    user: null
  }
};

// userがnullなので、addressにアクセスしようとしてもエラーにならずundefinedが返る
const zipCode = response.data.user?.address?.zipCode;
console.log(zipCode);
実行結果
undefined

これまではif (response.data && response.data.user)のように長々と書いていたコードを簡潔に記述できます。

エンジニアが意識すべき使い分けの指針

実際の開発現場では、どのように使い分けるのが正解なのでしょうか。

プロジェクトの規約にもよりますが、一般的なベストプラクティスをいくつか紹介します。

1. 自分からundefinedを代入しない

値が空であることを示したい場合、コード内で自らundefinedを代入するのは避けましょう。

「値がセットされていない状態」と「明示的に空にした状態」の区別がつかなくなるためです。

「意図的に空にするならnullを使う」というルールを徹底するだけで、デバッグの効率が向上します。

2. 関数のデフォルト引数を活用する

関数に引数が渡されなかった場合、その値はundefinedになります。

デフォルト引数を使用すると、undefinedの場合にのみデフォルト値を適用できます。

JavaScript
function setup(mode = "standard") {
  console.log(`現在のモード: ${mode}`);
}

setup();           // 引数がないので undefined -> "standard"
setup(undefined);  // undefinedを渡しても "standard"
setup(null);       // nullは「値がある」とみなされるため null
実行結果
"現在のモード: standard"
"現在のモード: standard"
"現在のモード: null"

3. JSONでのシリアライズを考慮する

JSON.stringify()を使用してオブジェクトを文字列に変換する際、値がundefinedのプロパティは完全に削除されます。

一方で、値がnullのプロパティはそのまま保持されます。

JavaScript
const obj = {
  key1: undefined,
  key2: null
};

console.log(JSON.stringify(obj));
実行結果
"{"key2":null}"

バックエンドとの通信で特定のキーを残しておく必要がある場合は、必ずnullを使用してください。

型チェックにおけるテクニック

変数が「nullかundefinedのどちらかであるか」を判定したいケースは非常に多いです。

その場合、あえて緩やかな比較(==)を利用する手法があります。

JavaScript
function processData(val) {
  // valが null または undefined の場合にのみ真となる
  if (val == null) {
    console.log("処理可能なデータがありません");
    return;
  }
  console.log("処理を開始します");
}

このように書くことで、val === null || val === undefinedという冗長な記述を避けることができます。

ただし、チーム開発では「厳密等価演算子(===)以外は禁止」というルールが設定されていることもあるため、プロジェクトの方針に合わせることが大切です。

TypeScriptとの親和性

2026年現在、JavaScript開発においてTypeScriptの利用はほぼ標準となっています。

TypeScriptでは、nullundefinedを異なる型として厳密に区別します。

「strictNullChecks」オプションを有効にすることで、これらの値が原因で発生する実行時エラー(通称:億ドルの過ち)をコンパイル時に検知できるようになります。

型定義においてstring | nullと指定することで、「文字列が入るか、あるいは意図的に空であるか」という意思表示をコード上で明確に行えます。

まとめ

JavaScriptにおけるnullundefinedは、どちらも「値がない」ことを表しますが、その背景にある意味合いは大きく異なります。

undefinedは「変数が未定義である」「初期化されていない」というシステム的な状態を指します。

一方でnullは「値が存在しないことを明示する」という開発者の意図的な宣言として使われます。

この違いを理解し、??演算子や?.演算子を適切に組み合わせることで、エラーに強く読みやすいコードを書くことができます。

最後に重要なポイントを振り返りましょう。

  • 変数の初期値や関数のデフォルトの戻り値はundefined
  • 「何もないこと」を明示的に代入する場合はnullを選択する。
  • typeof nullは歴史的経緯で"object"になる。
  • nullは数値の0undefinedは数値のNaNとして扱われる。
  • モダンな開発では???.を活用して安全にアクセスする。

これらの特性を正しく把握し、現場でのコーディングに活かしていきましょう。

URLをコピーしました!