JavaScriptのnull判定 - 初心者が知るべき基本と注意点

JavaScriptのnull判定について、基本的な概念から実践的な判定方法まで初心者向けに詳しく解説。null、undefined、空文字列の違いや、安全な判定方法、よくある間違いとその対策を具体的なコード例で学びます。

Learning Next 運営
36 分で読めます

みなさん、JavaScriptでエラーに困ったことはありませんか?

「Cannot read property of null」「undefined is not a function」こんなエラーメッセージを見たことがある方、きっと多いですよね。

実は、これらのエラーの多くはnull判定を正しく行わないことが原因なんです。 null判定をマスターすることで、エラーに強いプログラムを作ることができます。

この記事では、JavaScriptのnull判定について初心者向けに分かりやすく解説します。 基本的な概念から実践的な判定方法まで、一緒に学んでいきましょう!

nullって何?基本を理解しよう

nullの正体

nullは「何も値が入っていない」「値が意図的に存在しない」ことを表すJavaScriptの特別な値です。

簡単に言うと、「まだ値が決まっていない状態」や「空っぽの状態」を表すために使います。 例えば、ユーザーがまだ何も選択していない時などに使われます。

// nullの基本的な使い方
let userName = null; // 意図的に「値なし」を設定
let userAge = null; // まだ年齢が設定されていない
let selectedItem = null; // 何も選択されていない状態
console.log(userName); // null
console.log(typeof userName); // "object"

nullの判定方法も見てみましょう。

// nullかどうか確認
if (userName === null) {
console.log("ユーザー名が設定されていません");
}
console.log(userName == null); // true
console.log(userName === null); // true

null、undefined、空文字列の違い

JavaScriptには似たような「空」の状態を表す値が3つあります。 これらの違いを理解することが重要です。

// 3つの「空」の状態
let valueNull = null; // 意図的に「値なし」
let valueUndefined = undefined; // 値が定義されていない
let valueEmpty = ""; // 空の文字列
console.log("=== 型の確認 ===");
console.log(typeof valueNull); // "object"
console.log(typeof valueUndefined); // "undefined"
console.log(typeof valueEmpty); // "string"

実際の値と真偽値も確認してみましょう。

console.log("=== 値の確認 ===");
console.log(valueNull); // null
console.log(valueUndefined); // undefined
console.log(valueEmpty); // ""
console.log("=== 真偽値での判定 ===");
console.log(Boolean(valueNull)); // false
console.log(Boolean(valueUndefined)); // false
console.log(Boolean(valueEmpty)); // false

どれもfalseになりますが、用途が異なります。

// 実際の使い分け
let userProfile = {
name: "", // 空文字列:名前が未入力
age: null, // null:年齢が未設定
email: undefined // undefined:メールが定義されていない
};
console.log("プロフィール:", userProfile);

よくnullが出てくる場面

nullはプログラムの中でこんな場面によく登場します。

// DOM要素が見つからない場合
let element = document.getElementById("nonexistent");
console.log(element); // null
// 配列の検索で見つからない場合
let users = ["田中", "佐藤", "鈴木"];
let foundUser = users.find(user => user === "山田");
console.log(foundUser); // undefined

関数やオブジェクトでも出てきます。

// オブジェクトのプロパティが存在しない場合
let user = { name: "田中", age: 30 };
console.log(user.email); // undefined
// 関数が何も返さない場合
function doSomething() {
// return文がない
}
let result = doSomething();
console.log(result); // undefined
// 明示的にnullを設定
let selectedProduct = null; // 商品が選択されていない状態
let currentUser = null; // ログインしていない状態

これらの違いを理解することで、適切な判定ができるようになります。

基本的なnull判定方法

厳密等価演算子(===)を使おう

最も基本的で安全な判定方法は**厳密等価演算子(===)**を使うことです。

// 最も基本的で安全な判定方法
let value = null;
if (value === null) {
console.log("値はnullです");
}
if (value !== null) {
console.log("値はnullではありません");
} else {
console.log("値はnullです");
}

複数の値を判定する例も見てみましょう。

// 複数の値を判定
let values = [null, undefined, "", 0, false, "hello"];
values.forEach((val, index) => {
if (val === null) {
console.log(`${index}番目の値はnullです`);
} else {
console.log(`${index}番目の値はnullではありません: ${val}`);
}
});

この方法が最も正確で、予期しない動作を防げます。

等価演算子(==)との違い

等価演算子(==)を使うと、nullとundefinedが同じと判定されます。

// 等価演算子は null と undefined を同じと判定
let testNull = null;
let testUndefined = undefined;
console.log("=== 等価演算子 (==) ===");
console.log(testNull == null); // true
console.log(testNull == undefined); // true
console.log(testUndefined == null); // true
console.log("=== 厳密等価演算子 (===) ===");
console.log(testNull === null); // true
console.log(testNull === undefined); // false
console.log(testUndefined === null); // false

実用的な例を見てみましょう。

// 実用的な例:null または undefined のチェック
function processValue(value) {
if (value == null) {
console.log("値が null または undefined です");
return;
}
console.log(`値を処理します: ${value}`);
}
processValue(null); // 値が null または undefined です
processValue(undefined); // 値が null または undefined です
processValue(""); // 値を処理します:
processValue(0); // 値を処理します: 0

nullとundefinedの両方をチェックしたい場合は、==が便利な場合もあります。

typeof演算子を使った判定

undefinedを判定する場合はtypeof演算子も使えます。

// typeof演算子でundefinedを判定
let value1 = null;
let value2 = undefined;
let value3;
console.log("=== typeof演算子 ===");
console.log(typeof value1); // "object"
console.log(typeof value2); // "undefined"
console.log(typeof value3); // "undefined"

型を判定する関数を作ってみましょう。

// typeof を使った判定
function checkType(value) {
if (value === null) {
return "null";
}
if (typeof value === "undefined") {
return "undefined";
}
return typeof value;
}
console.log(checkType(null)); // "null"
console.log(checkType(undefined)); // "undefined"
console.log(checkType("hello")); // "string"
console.log(checkType(123)); // "number"

この方法で、値の型を正確に判定できます。

実際の場面で使える判定パターン

オブジェクトのプロパティを安全にチェック

オブジェクトのプロパティにアクセスする時は、注意が必要です。

// 安全なプロパティアクセス
let user = {
name: "田中太郎",
profile: {
age: 30,
email: "tanaka@example.com"
}
};
// 危険なアクセス方法
try {
console.log(user.profile.phone.number); // エラーが発生
} catch (error) {
console.log("エラー:", error.message);
}

安全にアクセスする関数を作りましょう。

// 安全なアクセス方法
function safeGetProperty(obj, ...keys) {
let current = obj;
for (let key of keys) {
if (current === null || current === undefined) {
return null;
}
current = current[key];
}
return current;
}
// 使用例
let phoneNumber = safeGetProperty(user, "profile", "phone", "number");
console.log(phoneNumber); // null
let email = safeGetProperty(user, "profile", "email");
console.log(email); // "tanaka@example.com"

モダンな書き方も覚えておきましょう。

// Optional Chaining (ES2020) を使用
let modernPhoneNumber = user.profile?.phone?.number;
console.log(modernPhoneNumber); // undefined
let modernEmail = user.profile?.email;
console.log(modernEmail); // "tanaka@example.com"

配列を安全に操作しよう

配列の中にnullやundefinedが含まれている場合の処理方法です。

// 配列の安全な操作
let numbers = [1, 2, 3, null, 5, undefined, 7];
// null/undefined を除外して処理
let validNumbers = numbers.filter(num => num !== null && num !== undefined);
console.log("有効な数値:", validNumbers); // [1, 2, 3, 5, 7]
// null/undefined を 0 に変換
let processedNumbers = numbers.map(num => {
if (num === null || num === undefined) {
return 0;
}
return num;
});
console.log("処理後の数値:", processedNumbers); // [1, 2, 3, 0, 5, 0, 7]

配列の要素を安全に取得する関数も作れます。

// 配列の要素を安全に取得
function safeGetArrayElement(arr, index) {
if (arr === null || arr === undefined) {
return null;
}
if (index < 0 || index >= arr.length) {
return null;
}
return arr[index];
}
let testArray = [10, 20, 30];
console.log(safeGetArrayElement(testArray, 1)); // 20
console.log(safeGetArrayElement(testArray, 5)); // null
console.log(safeGetArrayElement(null, 0)); // null

関数の引数を安全にチェック

関数に渡される引数をチェックする方法です。

// 関数の引数の安全な処理
function createUser(name, age, email) {
// 引数の検証
if (name === null || name === undefined || name === "") {
throw new Error("名前は必須です");
}
// デフォルト値の設定
let userAge = age !== null && age !== undefined ? age : 0;
let userEmail = email !== null && email !== undefined ? email : "";
return {
name: name,
age: userAge,
email: userEmail,
createdAt: new Date()
};
}
// 使用例
try {
let user1 = createUser("田中", 30, "tanaka@example.com");
console.log("ユーザー1:", user1);
let user2 = createUser("佐藤", null, undefined);
console.log("ユーザー2:", user2);
let user3 = createUser(null, 25, "test@example.com");
} catch (error) {
console.log("エラー:", error.message);
}

モダンな書き方でデフォルト引数を使うこともできます。

// よりモダンなアプローチ(デフォルト引数)
function createUserModern(name, age = 0, email = "") {
if (name === null || name === undefined || name === "") {
throw new Error("名前は必須です");
}
return {
name: name,
age: age,
email: email,
createdAt: new Date()
};
}
let modernUser = createUserModern("山田", undefined, "yamada@example.com");
console.log("モダンユーザー:", modernUser);

この方法で、関数をより安全に作ることができます。

新しい便利な判定方法

Nullish Coalescing Operator(??)

ES2020で追加された**null合体演算子(??)**はとても便利です。

// ES2020で追加された null合体演算子
let value1 = null;
let value2 = undefined;
let value3 = "";
let value4 = 0;
let value5 = false;
// ?? は null と undefined のみを判定
console.log(value1 ?? "デフォルト値"); // "デフォルト値"
console.log(value2 ?? "デフォルト値"); // "デフォルト値"
console.log(value3 ?? "デフォルト値"); // ""
console.log(value4 ?? "デフォルト値"); // 0
console.log(value5 ?? "デフォルト値"); // false

従来の||演算子との違いを見てみましょう。

console.log("=== || 演算子 ===");
console.log(value1 || "デフォルト値"); // "デフォルト値"
console.log(value2 || "デフォルト値"); // "デフォルト値"
console.log(value3 || "デフォルト値"); // "デフォルト値"
console.log(value4 || "デフォルト値"); // "デフォルト値"
console.log(value5 || "デフォルト値"); // "デフォルト値"

??は、nullとundefinedの場合のみデフォルト値を使います。 これにより、0や空文字列も有効な値として扱えます。

実用的な例を見てみましょう。

// 実用的な例
function processSettings(settings) {
let config = {
theme: settings?.theme ?? "light",
fontSize: settings?.fontSize ?? 16,
showNotifications: settings?.showNotifications ?? true,
maxRetries: settings?.maxRetries ?? 3
};
return config;
}
let userSettings = {
theme: null,
fontSize: 0,
showNotifications: false
};
let processedConfig = processSettings(userSettings);
console.log("設定:", processedConfig);

この方法で、設定値を安全に処理できます。

複数の条件を組み合わせた判定

より実用的な判定関数を作ってみましょう。

// 複数の条件を組み合わせた判定
function isNullOrEmpty(value) {
return value === null || value === undefined || value === "";
}
function isNullOrWhitespace(value) {
return value === null || value === undefined ||
(typeof value === "string" && value.trim() === "");
}
function hasValidValue(value) {
return value !== null && value !== undefined && value !== "";
}
// テスト
let testValues = [null, undefined, "", " ", "hello", 0, false];
console.log("=== null判定テスト ===");
testValues.forEach((val, index) => {
console.log(`${index}: ${JSON.stringify(val)}`);
console.log(` isNullOrEmpty: ${isNullOrEmpty(val)}`);
console.log(` isNullOrWhitespace: ${isNullOrWhitespace(val)}`);
console.log(` hasValidValue: ${hasValidValue(val)}`);
console.log("---");
});

配列やオブジェクトの判定も作れます。

// 配列やオブジェクトの判定
function isNullOrEmptyArray(arr) {
return arr === null || arr === undefined ||
!Array.isArray(arr) || arr.length === 0;
}
function isNullOrEmptyObject(obj) {
return obj === null || obj === undefined ||
typeof obj !== "object" || Object.keys(obj).length === 0;
}
// テスト
console.log("=== 配列・オブジェクトの判定 ===");
console.log(isNullOrEmptyArray(null)); // true
console.log(isNullOrEmptyArray([])); // true
console.log(isNullOrEmptyArray([1, 2, 3])); // false
console.log(isNullOrEmptyObject(null)); // true
console.log(isNullOrEmptyObject({})); // true
console.log(isNullOrEmptyObject({a: 1})); // false

実際のプロジェクトで役立つエラーハンドリング

DOM操作での安全な処理

DOM要素を扱う時は、要素が存在しない可能性があります。

// DOM要素の安全な取得と操作
class SafeDOM {
static getElementById(id) {
let element = document.getElementById(id);
return element !== null ? element : null;
}
static setText(id, text) {
let element = this.getElementById(id);
if (element !== null) {
element.textContent = text;
return true;
}
console.warn(`要素が見つかりません: ${id}`);
return false;
}
static getValue(id) {
let element = this.getElementById(id);
return element !== null ? element.value : null;
}
}
// 使用例(実際のHTML要素が存在する場合)
/*
SafeDOM.setText("title", "新しいタイトル");
SafeDOM.addClass("button", "active");
let inputValue = SafeDOM.getValue("user-input");
if (inputValue !== null) {
console.log("入力値:", inputValue);
} else {
console.log("入力要素が見つかりません");
}
*/

この方法で、DOM要素が存在しない場合のエラーを防げます。

フォーム入力の検証

ユーザーからの入力を安全に処理する方法です。

// フォームデータの安全な処理
class FormValidator {
static validateRequired(value, fieldName) {
if (value === null || value === undefined || value === "") {
return {
isValid: false,
message: `${fieldName}は必須です`
};
}
return { isValid: true, message: "" };
}
static validateEmail(email) {
if (email === null || email === undefined || email === "") {
return {
isValid: false,
message: "メールアドレスは必須です"
};
}
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return {
isValid: false,
message: "有効なメールアドレスを入力してください"
};
}
return { isValid: true, message: "" };
}
static validateForm(formData) {
let errors = [];
// 名前の検証
let nameResult = this.validateRequired(formData.name, "名前");
if (!nameResult.isValid) {
errors.push(nameResult.message);
}
// メールアドレスの検証
let emailResult = this.validateEmail(formData.email);
if (!emailResult.isValid) {
errors.push(emailResult.message);
}
return {
isValid: errors.length === 0,
errors: errors
};
}
}
// 使用例
function processFormSubmission(formData) {
let validationResult = FormValidator.validateForm(formData);
if (validationResult.isValid) {
console.log("フォーム送信成功:", formData);
return true;
} else {
console.log("フォーム検証エラー:");
validationResult.errors.forEach(error => {
console.log("- " + error);
});
return false;
}
}
// テストデータ
let testForms = [
{ name: "田中太郎", email: "tanaka@example.com" },
{ name: null, email: "invalid-email" },
{ name: "", email: "" }
];
console.log("=== フォーム検証テスト ===");
testForms.forEach((form, index) => {
console.log(`
テスト${index + 1}:`, form);
processFormSubmission(form);
});

この方法で、ユーザー入力を安全に検証できます。

よくある間違いと正しい対処法

型の混同

nullの型について間違いやすいポイントです。

// よくある間違い
function badNullCheck(value) {
// 間違い:typeof null は "object" になる
if (typeof value === "null") {
return "null値です";
}
return "null値ではありません";
}
console.log(badNullCheck(null)); // "null値ではありません"
// 正しい方法
function goodNullCheck(value) {
if (value === null) {
return "null値です";
}
return "null値ではありません";
}
console.log(goodNullCheck(null)); // "null値です"

完全な型チェック関数を作ってみましょう。

// 完全な型チェック関数
function checkValueType(value) {
if (value === null) {
return "null";
}
if (value === undefined) {
return "undefined";
}
return typeof value;
}
let testValues = [null, undefined, "", 0, false, [], {}];
testValues.forEach(val => {
console.log(`値: ${JSON.stringify(val)}, 型: ${checkValueType(val)}`);
});

等価演算子の誤用

等価演算子の使い分けに注意しましょう。

// 混同しやすい比較
console.log("=== 等価演算子の比較 ===");
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(null == 0); // false
console.log(null == false); // false
console.log(null == ""); // false
// 安全な判定方法
function safeCheck(value) {
if (value === null) {
return "null";
}
if (value === undefined) {
return "undefined";
}
return "値が存在";
}
// テスト
let testValues2 = [null, undefined, "", 0, false];
testValues2.forEach(val => {
console.log(`値: ${JSON.stringify(val)}`);
console.log(` 判定結果: ${safeCheck(val)}`);
});

ネストしたオブジェクトの安全な判定

深いオブジェクトにアクセスする時の注意点です。

// ネストしたオブジェクトの安全な判定
function safeGetNestedValue(obj, path) {
if (obj === null || obj === undefined) {
return null;
}
let keys = path.split('.');
let current = obj;
for (let key of keys) {
if (current === null || current === undefined) {
return null;
}
if (typeof current !== 'object') {
return null;
}
current = current[key];
}
return current;
}
// テスト用オブジェクト
let complexObject = {
user: {
profile: {
name: "田中太郎",
address: {
city: "東京",
zipCode: "123-4567"
}
},
settings: null
}
};
// 安全な取得
console.log("=== ネストオブジェクトの取得 ===");
console.log(safeGetNestedValue(complexObject, "user.profile.name"));
console.log(safeGetNestedValue(complexObject, "user.settings.theme"));
console.log(safeGetNestedValue(null, "user.profile.name"));
// モダンなアプローチ(Optional Chaining)
console.log("
=== Optional Chaining ===");
console.log(complexObject?.user?.profile?.name);
console.log(complexObject?.user?.settings?.theme);

Optional Chainingを使うことで、より簡潔に書けます。

まとめ

JavaScriptのnull判定について詳しく学んできました。

基本的な概念をおさらいしましょう。

  • null: 意図的に「値なし」を表す
  • undefined: 値が定義されていない状態
  • 空文字列: 長さが0の文字列
  • 型の違い: typeof nullは"object"

判定方法の重要なポイントはこちらです。

  • 厳密等価(===): 最も安全で推奨される方法
  • 等価(==): nullとundefinedを同一視
  • Nullish Coalescing(??): nullとundefinedのみを判定
  • Optional Chaining(?.): ネストオブジェクトの安全なアクセス

実践的な応用場面も覚えておきましょう。

  • DOM操作での要素の存在確認
  • フォーム処理での入力値の検証
  • エラーハンドリングでの予期しないnull値への対応

よくある間違いを避けることも大切です。

  • typeof nullの結果を誤解しない
  • 等価演算子を適切に使い分ける
  • ネストオブジェクトに安全にアクセスする

ベストプラクティスを実践しましょう。

  • 厳密等価演算子(===)を使用する
  • デフォルト値を適切に設定する
  • エラーハンドリングを実装する
  • モダンな構文(??、?.)を活用する

null判定を適切に実装することで、堅牢で信頼性の高いJavaScriptアプリケーションが作れるようになります。

まずは基本的な判定方法から始めて、徐々に高度なテクニックも試してみましょう。 ぜひ今日から、これらの知識を活用してエラーに強いWebアプリケーションを開発してみてくださいね!

関連記事