【JS応用|実務向け】プロのフロントエンド開発者が今すぐObject.hasOwnに切り替えるべき理由

導入: なぜObject.hasOwnが必要なのか

JavaScriptでオブジェクトのプロパティ存在確認を行う際、従来は Object.prototype.hasOwnProperty.call(obj, prop) という冗長な書き方が推奨されてきました。なぜなら、単純に obj.hasOwnProperty(prop) と書くと、オブジェクトが「nullプロトタイプ(Object.create(null)で作成されたもの)」である場合や、プロパティ名に「hasOwnProperty」という文字列が使われている場合にエラーや予期せぬ挙動を引き起こすからです。ES2022で導入された Object.hasOwn は、これらのリスクを解消し、より直感的で安全なプロパティチェックを可能にします。

基礎知識: プロトタイプチェーンとhasOwnPropertyの罠

JavaScriptのオブジェクトは、他のオブジェクトからプロパティを継承する「プロトタイプチェーン」という仕組みを持っています。多くのオブジェクトは Object.prototype を継承しており、そこに hasOwnProperty メソッドが存在します。

しかし、以下のケースでは従来の書き方は危険です。
1. Object.create(null) で作成されたオブジェクトには Object.prototype が存在せず、.hasOwnProperty メソッドを呼び出せません。
2. オブジェクト自体に “hasOwnProperty” というキーでデータが格納されている場合、メソッドが上書きされてしまい、意図しない挙動になります。

Object.hasOwn は静的メソッドであるため、インスタンスの状態に依存せず、常に安全にプロパティの存在を確認できます。

実装/解決策: 具体的な手順

Object.hasOwn(obj, prop) は、第一引数に確認対象のオブジェクト、第二引数にプロパティ名を渡します。戻り値は真偽値(boolean)です。このメソッドは、プロトタイプチェーンを辿らず、そのオブジェクトが「直接」持っているプロパティのみを判定します。

サンプルプログラム: 実践的な使用例

以下は、安全なプロパティチェックを行うための実装例です。

// 比較対象のオブジェクト
const user = {
  id: 1,
  name: 'Tanaka',
  // あえてhasOwnPropertyという名前のプロパティを持たせる
  hasOwnProperty: '危険なキー' 
};

// 1. 従来の書き方(エラーになる可能性がある)
// user.hasOwnProperty('id') は、上記のプロパティで上書きされているため失敗する
try {
  console.log(user.hasOwnProperty('id')); 
} catch (e) {
  console.log('エラーが発生しました');
}

// 2. Object.hasOwn を使用した安全な書き方
// プロトタイプチェーンを無視して、オブジェクト自身が持つプロパティだけを確認
if (Object.hasOwn(user, 'id')) {
  console.log('idプロパティは存在します');
}

// 3. Object.create(null) で作成されたオブジェクトへの対応
const safeObj = Object.create(null);
safeObj.key = 'value';

// Object.hasOwnなら、プロトタイプを持たないオブジェクトでも安全に判定できる
console.log(Object.hasOwn(safeObj, 'key')); // true

応用・注意点: 現場で役立つ補足情報

Object.hasOwn を利用する際の注意点として、ブラウザの対応状況が挙げられます。現在、主要なモダンブラウザおよびNode.js 16.9.0以降であれば問題なく動作します。しかし、古い環境をサポートする必要がある場合は、以下のポリフィルを検討してください。

ポリフィル(非対応環境用):

if (typeof Object.hasOwn !== 'function') {
  Object.defineProperty(Object, 'hasOwn', {
    value: (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop),
    configurable: true,
    enumerable: false,
    writable: true
  });
}

現場のコードベースでは、in 演算子と混同しないよう注意しましょう。in 演算子は「プロトタイプチェーン上のプロパティも存在とみなす」ため、純粋にそのオブジェクトが所有する値だけをチェックしたい場合は、必ず Object.hasOwn を選択するのが正解です。

タイトルとURLをコピーしました