Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2015年7月以降、すべてのブラウザーで利用可能です。
Object.defineProperty() は静的メソッドで、あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返します。
プロパティを定義するオブジェクトです。
prop文字列または Symbol で、定義または変更するプロパティのキーを指定します。
descriptor定義または変更するプロパティの記述子です。
指定したプロパティが追加または変更された、関数に渡されたオブジェクト。
Object.defineProperty() で、あるオブジェクトのプロパティを明示的に追加または変更することができます。代入による通常のプロパティ追加では、プロパティ列挙 (for...in ループや Object.keys() メソッドなど) に現れ、値は変更可能で、また削除も可能なプロパティが生成されます。このメソッドでは、これらの詳細事項を既定値から変えることが可能です。既定では、 Object.defineProperty() を使って追加されたプロパティは書き込み不可、列挙不可、構成不可になります。加えて、 Object.defineProperty() は内部メソッドの [[DefineOwnProperty]] を [[Set]] の代わりに使用しますので、プロパティが既に存在する場合でもセッターを呼び出しません。
プロパティの記述子は、データ記述子とアクセサー記述子の二つに分かれます。データ記述子は値を持つプロパティで、その値は書き換え可能にも不可能にもできます。アクセサー記述子は、関数のゲッターとセッターの組で表されるプロパティです。記述子はこれら二種類のどちらかでなければならず、両方になることはできません。
どちらの形でも記述子はオブジェクトで表現します。共通して以下のオプションのキーを持つことができます (注: ここでいう既定値とは、Object.defineProperty() を使ってプロパティを定義する場合です)。
configurableこれが false に設定されていた場合、
既定値は false です。
enumerabletrue である場合のみ、このプロパティは対応するオブジェクトでのプロパティ列挙に現れます。既定値は false です。
データ記述子は以下のオプションキーも持ちます。
valueプロパティに関連づけられた値です。有効な JavaScript の値(数値、オブジェクト、関数など)である必要があります。既定値は undefined です。
writabletrue である場合のみ、プロパティに関連づけられた値は代入演算子で変更することができます。
既定値は false です。
アクセサー記述子の場合はオプションとして次のキーも持つことができます。
getプロパティのゲッターとなる関数で、ゲッターを設けない場合は undefined です。プロパティにアクセスするとこの関数が引数なしでコールされます。この関数内で this はアクセスしようとしたプロパティを持つオブジェクトになります (プロパティを定義するために作成した記述子オブジェクトではありません)。返値はこのプロパティの値として使われます。 既定値は undefined です。
setプロパティのセッターとなる関数で、セッターがない場合は undefined です。プロパティに値が割り当てられたとき、その値を引数としてこの関数がコールされます。この関数内で this は割り当てようとしたプロパティを持つオブジェクトになります。 既定値は undefined です。
記述子に value, writable, get, set のいずれのキーもない場合、データ記述子として扱われます。記述子がデータ記述子(value または writable を持つため)であり、かつアクセサー記述子(get または set を持つため)である場合、例外が発生します。
これらのキーは必ずしも記述子が直接所有しているとは限らないことに留意してください。継承されたプロパティも同様です。これらの既定を確実に保持するためには、記述子オブジェクトのプロトタイプチェーンにある既存のオブジェクトを前もって凍結するか、すべてのオプションを明示的に指定するか、 null プロトタイプオブジェクトを作成します。
プロパティが既に存在する場合、 Object.defineProperty() は記述子の値とプロパティの現在の構成に従ってプロパティを変更しようとします。
古い記述子の configurable 属性が false に設定されていた場合、そのプロパティは 構成不可 と言います。設定不可能なアクセサープロパティの属性を変更することはできませんし、データプロパティとアクセサープロパティの種類を切り替えることもできません。 writable: true のデータプロパティでは、値を変更して writable 属性を true から false に変更することが可能です。データプロパティで元の値と同じ値を定義する場合を除き、設定不可能なプロパティ属性(許可されている場合は value と writable を除く)を変更しようとすると TypeError が発生します。
現在のプロパティが構成可能な場合、属性を undefined に定義すると、その属性は効果的に削除されます。例えば、 o.k がアクセサープロパティである場合、 Object.defineProperty(o, "k", { set: undefined }) とするとセッターを除去し、k はゲッターのみを持つことになるので、読み取り専用になります。新しい記述子に属性がない場合、古い記述子の属性値は保持されます(暗黙的に undefined に再定義されることはありません)。異なる「風味」の記述子を与えることで、データとアクセサープロパティを切り替えることが可能です。例えば、新しい記述子が(value または writable を持つ)データ記述子の場合、元の記述子の get 属性と set 属性は両方とも削除されます。
オブジェクトに指定されたプロパティが存在しないとき、Object.defineProperty() は指定された形で新たなプロパティを生成します。記述子のキーは省略することができ、そのようなキーには既定値が適用されます。
既存のプロパティを変更するとき、操作が成功するか、何もしないか、TypeErrorが発生するかは、現在のプロパティ構成によって決まります。
writable プロパティ属性が false の場合、そのプロパティは「書き込み不可」になります。代入ができなくなります。書き込み不可能なプロパティに書き込もうとすると、変更されず、厳格モードではエラーになります。
enumerable プロパティ属性は、そのプロパティが Object.assign() や スプレッド演算子で認識されるかどうかを定義します。 Symbol 以外のプロパティでは、 for...in ループや Object.keys() に現れるかどうかも定義します。詳細情報については、プロパティの列挙可能性と所有権を参照してください。
configurable 属性は、プロパティをオブジェクトから削除できるかとプロパティの属性 (value と writable 以外) を変更できるかを制御します。
この例は、構成可能でないアクセサープロパティを示しています。
o.a の configurable 属性が true である場合、エラーが発生することなく最終的にプロパティが削除されます。
この例は、構成可能ではないが書き込み可能なデータプロパティを示しています。プロパティの value は変更可能で、 writable は true から false に切り替えることができます。
この例は構成可能な、しかし書き込み不可能なデータプロパティを示しています。プロパティの value は defineProperty で置き換えることができ(代入演算子ではなく)、writable は切り替えることができます。
この例は構成可能でなく、書き込み不可のデータプロパティを示しています。プロパティの値を含め、プロパティの属性を更新する方法はありません。
属性の既定値がどう適用されるかを考えることは重要です。値の割り当てにプロパティアクセサーを用いた場合と Object.defineProperty() を用いた場合とでは、以下の例で示したとおりに違いがあります。
例として自律的に記録を行うオブジェクトを作成してみます。temperature プロパティに値が代入されると、配列 archive に要素が一つ追加されます。
次の例では、ゲッターが常に同じ値を返すようにしています。
アクセサープロパティを継承されると、その派生クラスでもプロパティがアクセスされたり書き換えられるときに get と set が呼ばれます。これらのメソッドが値を保持するために変数を使っていると、すべてのオブジェクトがその値を共有することになります。
この問題を回避する方法は値を別のプロパティで保持することです。get と set メソッド内で this はアクセス/変更されようとしているプロパティを納めるオブジェクトを指しています。
アクセサープロパティとは違い、データプロパティは常にオブジェクト自身に格納されるのであって、プロトタイプに格納されるわけではありません。しかし、書き込み不可能なデータプロパティを継承している場合、継承先オブジェクトでも書き換えは阻止されます。
| ECMAScript® 2027 Language Specification # sec-object.defineproperty |
ブラウザー互換性一覧表を表示するには、JavaScript を有効にしてください。
より良いインターネットのための青写真。
このコンテンツの一部は、©1998–2026 個人の mozilla.org 協力者です。コンテンツはクリエイティブ・コモンズ・ライセンスのもとで利用できます。