導入:なぜオブジェクトの拡張を制限する必要があるのか?
JavaScriptで開発をしていると、「予期せぬタイミングでオブジェクトに新しいプロパティを追加されたくない」という場面に出くわすことがあります。例えば、設定データや重要な定数オブジェクトなどです。[[Extensible]]という内部プロパティを理解して制御できるようになると、意図しないデータの上書きや追加を防ぎ、より堅牢なプログラムを書くことができます。
基礎知識:[[Extensible]]とは?
JavaScriptのすべてのオブジェクトは、内部的に「拡張可能かどうか(Extensible)」を示すフラグを持っています。これが「true」であれば、新しいプロパティを追加できます。逆に「false」に設定すると、そのオブジェクトには新しいプロパティを追加することが一切できなくなります。
重要ポイントは、「拡張不可にしても、既存のプロパティの書き換えは可能」という点です。あくまで「新しいものを追加させない」ための仕組みだと覚えておきましょう。
実装:オブジェクトを拡張不可にする方法
オブジェクトの拡張を制御するには、Object.preventExtensions() というメソッドを使用します。また、現在の状態を確認するには Object.isExtensible() を使います。
手順は以下の通りです。
1. Object.isExtensible() で現在の状態を確認する。
2. Object.preventExtensions() で拡張を禁止する。
3. 新しいプロパティを追加しようとして、動作を確認する。
サンプルプログラム
以下のコードをブラウザのコンソールなどに貼り付けて、動作を試してみてください。
// 1. 通常のオブジェクトを作成
const user = { name: "太郎" };
console.log("拡張可能か確認:", Object.isExtensible(user)); // true
// 2. 拡張を禁止する
Object.preventExtensions(user);
console.log("禁止後の状態:", Object.isExtensible(user)); // false
// 3. 新しいプロパティを追加してみる
user.age = 25;
// 4. 結果の確認
console.log(user); // { name: "太郎" } ※ageは追加されない
console.log(user.age); // undefined
// ただし、既存のプロパティの変更は可能
user.name = "次郎";
console.log(user.name); // "次郎" と変更される
応用・注意点:現場で役立つ補足
実務でさらに厳格な制御が必要な場合は、以下のメソッドと混同しないように注意しましょう。
Object.seal()
拡張を禁止した上で、「プロパティの削除」も禁止します。設定値などを固定する際によく使われます。
Object.freeze()
拡張、削除、さらに「既存プロパティの変更(書き込み)」まで全て禁止します。完全に「読み取り専用」にしたい場合に最適です。
注意点:
一度「拡張不可(preventExtensions)」に設定したオブジェクトを、後から「拡張可能」に戻すことはできません。この操作は不可逆的ですので、設定するタイミングには注意してください。また、Strictモード(’use strict’;)で実行している場合、拡張不可のオブジェクトにプロパティを追加しようとするとエラーが発生します。開発中はStrictモードを有効にして、バグを早期発見できるようにしておきましょう。