JavaScript

Object.seal()メソッド

 編集:2022.07.28 by T.A.

オブジェクトを封印して、新しいオブジェクトを追加することを抑制し、すべての既存のプロパティを設定変更不可にします。現存するプロパティの値は、書き込み可能である限り変更できます。

Object.seal(obj)
obj 封印するオブジェクトです。
戻り値

封印されたオブジェクトです。

解説

既定では、オブジェクトは拡張可能(新しいプロパティを追加できる状態)です。オブジェクトを封印することで、新しいオブジェクトの追加を抑制し、すべての既存のプロパティを設定変更を不可にします。これは、オブジェクトにあるプロパティ一式を固定かつ不変にする効果があります。
プロパティを設定変更不可にすることで、データ プロパティからアクセサー プロパティへの変換やその逆を抑制しますが、データ プロパティの値の変更は抑制しません。
封印されたオブジェクトでプロパティの削除や追加、あるいはデータ プロパティからアクセサー プロパティへの変換およびその逆を試みると、暗黙的あるいは TypeError エラーを発生させて(もっとも一般的には strict mode において、ただしこれに限定はされません)失敗します。

プロトタイプ チェインには手をつけず、そのままにします。ただし、__proto__ プロパティは同様に封印されます。

Object.freeze() との比較

Object.freeze() で凍結されたオブジェクトに存在するプロパティは不変になります。Object.seal() で封印されたオブジェクトに存在するプロパティを変更することができます。

Object.seal の使用
var obj = {
  prop: function() {},
  foo: 'bar'
};

// 新しいプロパティは追加でき、既存のプロパティは変更や削除ができます。
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;

var o = Object.seal(obj);	//オブジェクトを封印

D=o === obj;	//=true
D=Object.isSealed(obj);	//=true

obj.foo = 'quux';	// 封印されたオブジェクトで、プロパティの値の変更は依然としてできます。

// しかし、データ プロパティからアクセサ プロパティの変換やその逆はできません。
Object.defineProperty(obj, 'foo', {
  get: function() { return 'g'; }
});	// TypeError が発生

// プロパティの値の変更を除き、あらゆる変更が失敗します。
obj.quaxxor = 'the friendly duck';	// 暗黙的にプロパティは追加されません。
delete obj.foo;	// 暗黙的にプロパティは削除されません。

// また、strict モードではこれらの試みに対して TypeErrors が発生します。
function fail() {
  'use strict';
  delete obj.foo;	// TypeError が発生
  obj.sparky = 'arf';	// TypeError が発生
}
fail();

// Object.defineProperty を用いて追加しようとしてもエラーが発生します
Object.defineProperty(obj, 'ohai', {
  value: 17
});	// TypeError が発生
Object.defineProperty(obj, 'foo', {
  value: 'eit'
});	// 既存のプロパティの値を変更
非オブジェクトの強制

ES5 では、このメソッドへの引数がオブジェクトではない場合(プリミティブである場合)、TypeError になります。ES2015 では、オブジェクトではない引数は封印された通常のオブジェクトと同様に扱われ、単純にそれを返します。

Object.seal(1);	// TypeError: 1 is not an object(ES5 code)
Object.seal(1);	//=1(ES2015 code)

テスト