1. 導入:なぜObject.isSealedを知る必要があるのか
フロントエンド開発において、APIから取得した設定値や、アプリケーション内で共有する定数オブジェクトを「意図せず変更されたくない」というケースは多々あります。JavaScriptにはオブジェクトの変更を制限するAPIがいくつか存在しますが、その中でも「Object.isSealed」は、オブジェクトが「封印(Sealed)」されているかどうかを判定するための重要なメソッドです。この仕組みを理解することで、予期せぬプロパティの追加・削除によるバグを未然に防ぐ堅牢なコードを書くことができます。
2. 基礎知識:オブジェクトの「封印」とは何か
JavaScriptのオブジェクトはデフォルトでは自由に変更可能です。しかし、Object.seal()メソッドを使用すると、そのオブジェクトは「封印」状態になります。
封印されたオブジェクトの制約は以下の通りです。
・新しいプロパティを追加できない。
・既存のプロパティを削除できない。
・プロパティの設定(列挙可能か、書き込み可能かなど)を変更できない。
・ただし、「既存のプロパティの値」の変更は可能。
Object.isSealedは、対象のオブジェクトがこの「封印」状態にあるかを真偽値(true/false)で返します。空のオブジェクトも、何らかの理由で封印されていればtrueとなります。
3. 実装/解決策:判定と封印の活用
実務では、外部ライブラリから渡されたオブジェクトや、状態管理ライブラリ内の値が、予期せず拡張されていないかを確認する用途で利用します。また、Object.seal()とセットで使い、オブジェクトの構造を固定したい場合に使用するのが一般的です。
4. サンプルプログラム
以下のコードは、オブジェクトの封印状態を確認し、実際に封印を行った後に挙動が変わる様子をシミュレートしたものです。
// テスト用のオブジェクト
const config = {
theme: 'dark',
version: 1.0
};
// 1. 封印前の状態を確認
console.log('封印されていますか?:', Object.isSealed(config)); // false
// 2. オブジェクトを封印する
Object.seal(config);
// 3. 封印後の状態を確認
console.log('封印されていますか?:', Object.isSealed(config)); // true
// 4. 封印後の挙動テスト
try {
// 既存プロパティの値の変更は可能
config.version = 2.0;
console.log('値の変更成功:', config.version);
// プロパティの追加は不可(厳格モードではエラー、通常は無視される)
config.apiEndpoint = 'https://api.example.com';
// プロパティの削除は不可
delete config.theme;
} catch (e) {
console.error('エラーが発生しました', e);
}
console.log('最終的なオブジェクト:', config);
5. 応用・注意点:現場で陥りやすい罠
1. 厳格モード(’use strict’)の使用
非厳格モードでは、封印されたオブジェクトに対してプロパティの追加・削除を行っても、JavaScriptは単にそれを無視します。しかし、開発中にエラーに気づくためにも、必ず厳格モード(’use strict’)を使用してください。厳格モードであれば、封印されたオブジェクトのプロパティを削除しようとした際にTypeErrorがスローされます。
2. Object.freezeとの違い
よく混同されるのが「Object.freeze」です。freezeは「値の変更」すらも禁止します。
・Object.seal: 値の変更はOK、構造変更(追加・削除)はNG。
・Object.freeze: 値の変更も構造変更もすべてNG。
用途に合わせて使い分けることが重要です。
3. プロトタイプチェーンへの影響
Object.seal()は対象のオブジェクト自体を封印しますが、プロトタイプチェーン上のオブジェクトまで封印するわけではありません。深い階層のオブジェクト(ネストされたオブジェクト)を保護したい場合は、再帰的に処理を行うユーティリティ関数を自作するか、Immerのようなイミュータブルな状態を扱うライブラリの採用を検討しましょう。