【JavaScript】オブジェクトのプロパティ存在確認!hasOwnPropertyとin演算子の確実な使い分け

目次

概要

外部APIから取得したJSONデータや、オプション設定オブジェクトにおいて、「特定のキーが存在するかどうか」を判定する処理は不可欠です。

単に obj.key でアクセスすると、プロパティが存在しない場合も、値が undefined の場合も区別がつきません。

正確な検証を行うために、hasOwnProperty メソッドや in 演算子を使用し、キーの有無を厳密に判定する方法を解説します。

仕様(入出力)

プロパティ確認メソッド比較

メソッド・演算子意味戻り値特徴
obj.hasOwnProperty('key')オブジェクト自身がそのキーを持っているか判定する。Boolean
(true/false)
推奨。プロトタイプチェーン(親オブジェクト)は検索しない。
'key' in objオブジェクトがそのキーを持っているか判定する。Boolean親(プロトタイプ)にあるプロパティも true になる。
obj.key !== undefined値が定義されているか判定する。Booleanキーが存在しても、値が undefined の場合は false になり区別できない。
  • 入力: 検査対象のキー名(文字列)
  • 出力: 存在有無の真偽値

基本の使い方

1. サーバー設定の有無を確認する

設定オブジェクトに特定のオプションが含まれているかを確認します。

const serverConfig = {
    host: 'localhost',
    port: 8080,
    timeout: null // キーは存在するが値はnull
};

// hasOwnProperty: キーそのものの有無
console.log(serverConfig.hasOwnProperty('host'));    // true
console.log(serverConfig.hasOwnProperty('ssl'));     // false

// 値のチェックとの違い
console.log(serverConfig.hasOwnProperty('timeout')); // true (キーはある)
console.log(serverConfig.timeout != null);           // false (値はない)

2. in 演算子との違い

継承されたプロパティ(toStringなど)の扱いが異なります。

const config = { debug: true };

console.log('toString' in config);            // true (Objectの機能を継承しているため)
console.log(config.hasOwnProperty('toString')); // false (自身には定義していない)

コード全文(HTML / JavaScript)

APIレスポンスの解析システムを構築します。

レスポンスオブジェクト内に「error」プロパティが含まれているかどうかを判定し、処理を正常系と異常系に分岐させます。

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API Response Validator</title>
    <style>
        .system-panel {
            font-family: 'Consolas', monospace;
            max-width: 500px;
            padding: 20px;
            background-color: #1e1e1e;
            color: #d4d4d4;
            border-radius: 8px;
        }
        h3 { border-bottom: 1px solid #333; padding-bottom: 10px; color: #569cd6; }
        .response-box {
            background-color: #2d2d2d;
            padding: 15px;
            margin-bottom: 15px;
            border-radius: 4px;
            border-left: 5px solid #555;
        }
        .response-box.success { border-left-color: #4caf50; }
        .response-box.error { border-left-color: #f44336; }
        
        .btn-group { display: flex; gap: 10px; }
        button {
            padding: 10px 15px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            color: white;
        }
        .btn-ok { background-color: #4caf50; }
        .btn-fail { background-color: #f44336; }
        
        #log-area { margin-top: 15px; white-space: pre-wrap; }
    </style>
</head>
<body>

<div class="system-panel">
    <h3>API Response Validator</h3>
    
    <div class="btn-group">
        <button id="btn-success" class="btn-ok">成功レスポンス受信</button>
        <button id="btn-error" class="btn-fail">エラーレスポンス受信</button>
    </div>

    <div id="log-area">待機中...</div>
</div>

<script src="validator.js"></script>
</body>
</html>

JavaScript

/**
 * レスポンス検証スクリプト
 * プロパティの有無による処理分岐
 */

// 1. 成功時のレスポンスデータ
const successResponse = {
    status: 200,
    payload: { items: ['ItemA', 'ItemB'] },
    timestamp: 1672531200
};

// 2. エラー時のレスポンスデータ
// payloadプロパティが存在せず、errorプロパティが存在する
const errorResponse = {
    status: 500,
    error: { code: 'E001', message: 'Internal Server Error' }
};

// DOM要素
const logArea = document.getElementById('log-area');
const btnSuccess = document.getElementById('btn-success');
const btnError = document.getElementById('btn-error');

/**
 * レスポンスを解析して表示する関数
 * @param {Object} data APIからのレスポンスオブジェクト
 */
const processResponse = (data) => {
    let html = '';

    // ★ hasOwnPropertyによる分岐
    // "error" というキーを持っているかで判定する
    if (data.hasOwnProperty('error')) {
        // エラー処理ルート
        html = `
        <div class="response-box error">
            [Alert] エラーを検出しました<br>
            Code: ${data.error.code}<br>
            Msg: ${data.error.message}
        </div>`;
    } 
    // "payload" というキーを持っているかで判定
    else if (data.hasOwnProperty('payload')) {
        // 正常処理ルート
        html = `
        <div class="response-box success">
            [Info] データ受信成功<br>
            Items: ${data.payload.items.join(', ')}
        </div>`;
    } 
    else {
        // 想定外のフォーマット
        html = '<div class="response-box">[Warning] 不明なデータ形式です</div>';
    }

    logArea.innerHTML = html;
};

// イベントリスナー
btnSuccess.addEventListener('click', () => processResponse(successResponse));
btnError.addEventListener('click', () => processResponse(errorResponse));

まとめ

オブジェクトのプロパティを確認する際、単純な obj.key へのアクセスでは、値が 0falsenull の場合に誤判定を引き起こす可能性があります。データの構造そのものを検証する場合は、必ず hasOwnProperty を使用して「キーが存在するか」をチェックしてください。なお、最新のJavaScript(ES2022以降)では、より安全な Object.hasOwn(obj, 'key') というメソッドも導入されていますが、基本的な考え方は同じです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次