Object.seal()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Object.seal() 静的メソッドは、オブジェクトを封印します。オブジェクトを封印すると、拡張を抑止し、既存のすべてのプロパティを構成不可にします。封印されたオブジェクトは、固定されたプロパティ一式を持ちます。新しいプロパティを追加したり、既存のプロパティを除去したり、列挙可能性や構成可能性を変更したり、プロトタイプを再割り当てしたりすることはできません。既存のプロパティの値は、書き込み可能である限り変更することができます。 seal() は渡したオブジェクトを返します。

試してみましょう

構文

js
Object.seal(obj)

引数

obj

封印するオブジェクトです。

返値

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

解説

オブジェクトを封印すると、拡張を抑止し、既存のすべてのプロパティの記述子configurable: false に変更します。これは、オブジェクトにあるプロパティ一式を固定かつ不変にする効果があります。すべてのプロパティを構成不可にすることで、データプロパティからアクセサプロパティへの変換やその逆を抑制しますが、データプロパティの値の変更は抑制しません。封印されたオブジェクトでプロパティの削除や追加、あるいはデータプロパティからアクセサプロパティへの変換およびその逆をしようとすると、暗黙的に失敗するか、(一般的に厳格モードにおいてですが、それに限らず) TypeError が発生して失敗します。

プライベートプロパティにはプロパティ記述子の概念はありません。プライベートプロパティは、オブジェクトが封印されているかどうかに関わらず、オブジェクトに追加したり除去したりすることはできません。

プロトタイプチェーンには手をつけず、そのままにします。ただし、拡張の抑止の影響により、 [[Prototype]] は再代入できません。

Object.freeze() とは異なり、 Object.seal() で封印されたオブジェクトは、書き込み可能である限り、既存のプロパティを変更することができます。

Object.seal の使用

js
const obj = {
  prop() {},
  foo: "bar",
};

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

const o = Object.seal(obj);

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

// 封印されたオブジェクトでも、プロパティの値は変更できる
zobj.foo = "quux";

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

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

// また、厳格モードではこれらの試みに対して TypeError が発生します。
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 では、オブジェクトではない引数は封印された通常のオブジェクトと同様に扱われ、単純にそれを返します。

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

Object.seal(1);
// 1                             (ES2015 code)

仕様書

Specification
ECMAScript Language Specification
# sec-object.seal

ブラウザーの互換性

BCD tables only load in the browser

関連情報