#属性説明オブジェクト

概要

JavaScript は、オブジェクトのプロパティを記述し、そのプロパティが書き込み可能かどうか、トラバース可能かどうかなど、その動作を制御するための内部データ構造を提供します。この内部データ構造は「属性オブジェクト」と呼ばれます。各属性には、対応する独自の属性説明オブジェクトがあり、属性に関するメタ情報が格納されます。

以下はプロパティ記述オブジェクトの例です。

{
  値: 123、
  書き込み可能: false、
  列挙可能: true、
  構成可能: false、
  取得: 未定義、
  セット: 未定義
}

属性説明オブジェクトは 6 つのメタ属性を提供します。

(1)「値」

value はこのプロパティのプロパティ値で、デフォルトは undefine です。

(2)「書き込み可能」

「writable」は属性値(値)が変更可能か(つまり書き込み可能か)を示すブール値であり、デフォルトは「true」である。

(3)「数えられる」

enumerable は、プロパティが通過可能かどうかを示すブール値です。デフォルトは true です。 「false」に設定すると、特定の操作 (「for...in」ループ、「Object.keys()」など) はこのプロパティをスキップします。

(4)「構成可能」

configurable はプロパティの構成可能性を示すブール値で、デフォルトは true です。 「false」に設定すると、特定の操作でプロパティ記述オブジェクトを書き換えることができなくなります。たとえば、プロパティを削除したり、さまざまなメタプロパティ (「value」プロパティを除く) を変更したりすることはできません。言い換えれば、「configurable」属性はプロパティ記述オブジェクトの書き込み可能性を制御します。

(5)「ゲット」

get はプロパティの値関数 (getter) を表す関数です。デフォルトは unknown です。

(6)「セット」

set はプロパティの値関数 (setter) を表す関数です。デフォルトは unknown です。

Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor() メソッドはプロパティ説明オブジェクトを取得できます。最初のパラメータはターゲット オブジェクトで、2 番目のパラメータはターゲット オブジェクトの特定の属性名に対応する文字列です。

var obj = { p: 'a' };

Object.getOwnPropertyDescriptor(obj, 'p')
// オブジェクト { 値: "a",
// 書き込み可能: true,
// 列挙可能: true,
// 設定可能: true
// }

上記のコードでは、Object.getOwnPropertyDescriptor() メソッドが obj.p のプロパティ記述オブジェクトを取得します。

Object.getOwnPropertyDescriptor() メソッドは、継承されたプロパティではなく、オブジェクト自体のプロパティにのみ使用できることに注意してください。

var obj = { p: 'a' };

Object.getOwnPropertyDescriptor(obj, 'toString')
// 未定義

上記のコードでは、「toString」は「obj」オブジェクトによって継承されるプロパティであり、「Object.getOwnPropertyDescriptor()」では取得できません。

Object.getOwnPropertyNames()

Object.getOwnPropertyNames メソッドは、プロパティが走査可能かどうかに関係なく、パラメータ オブジェクト自体のすべてのプロパティのプロパティ名をメンバーとする配列を返します。

var obj = Object.defineProperties({}, {
  p1: { 値: 1、列挙可能: true }、
  p2: { 値: 2、列挙可能: false }
});

Object.getOwnPropertyNames(obj)
// ["p1", "p2"]

上記のコードでは、「obj.p1」は走査可能ですが、「obj.p2」は走査できません。 Object.getOwnPropertyNames は両方を返します。

これは、オブジェクト自体の走査可能なプロパティのすべてのプロパティ名のみを返す Object.keys の動作とは異なります。

Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]

Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ['hasOwnProperty',
// '値',
// 'コンストラクター',
// 'toLocaleString',
// 'isPrototypeOf',
// 'propertyIsEnumerable',
// 'toString']

上記のコードでは、配列自体の length プロパティはトラバース可能ではなく、Object.keys はこのプロパティを返しません。 2 番目の例の Object.prototype もオブジェクトであり、すべてのインスタンス オブジェクトはそれを継承しますが、それ自体のプロパティは通過できません。

Object.defineProperty()、Object.defineProperties()

Object.defineProperty() メソッドを使用すると、プロパティを通じてオブジェクトを記述し、プロパティを定義または変更し、変更されたオブジェクトを返すことができます。その使用方法は次のとおりです。

Object.defineProperty(オブジェクト, プロパティ名, 属性オブジェクト)

Object.defineProperty メソッドは、次のように 3 つのパラメータを受け入れます。

  • オブジェクト: 属性が配置されているオブジェクト
  • propertyName: プロパティ名を示す文字列 -attributsObject: 属性説明オブジェクト

たとえば、定義「obj.p」は次のように記述できます。

var obj = Object.defineProperty({}, 'p', {
  値: 123、
  書き込み可能: false、
  列挙可能: true、
  設定可能: false
});

obj.p // 123

obj.p = 246;
obj.p // 123

上記のコードでは、Object.defineProperty() メソッドが obj.p プロパティを定義します。プロパティ記述オブジェクトの「writable」プロパティが「false」であるため、「obj.p」プロパティは書き込み可能ではありません。ここでの Object.defineProperty メソッドの最初のパラメータは {} (新しく作成された空のオブジェクト) であり、p プロパティはこの空のオブジェクトに直接定義され、このオブジェクト (Object) を返すことに注意してください。 .defineProperty() の一般的な使用法。

プロパティがすでに存在する場合、Object.defineProperty() メソッドは、プロパティのプロパティ説明オブジェクトを更新することと同じです。

複数のプロパティを一度に定義または変更する場合は、Object.defineProperties() メソッドを使用できます。

var obj = Object.defineProperties({}, {
  p1: { 値: 123、列挙可能: true }、
  p2: { 値: 'abc'、列挙可能: true }、
  p3: { get: function () { return this.p1 + this.p2 },
    列挙可能:真、
    設定可能:true
  }
});

obj.p1 // 123
obj.p2 // "abc"
obj.p3 // "123abc"

上記のコードでは、Object.defineProperties()obj オブジェクトの 3 つのプロパティを同時に定義します。このうち、p3 属性は値関数 get を定義します。つまり、属性が読み取られるたびに、この値関数が呼び出されます。

値関数 get (または値関数 set) が定義されると、writable 属性を true に設定することはできません。また、同時に value 属性を定義することもできません。そうでない場合はエラーが発生します。報告されます。

var obj = {};

Object.defineProperty(obj, 'p', {
  値: 123get: function() { 戻り値 456 }
});
// TypeError: 無効なプロパティです。
// プロパティはアクセサーと書き込み可能または値の両方を持つことはできません

Object.defineProperty(obj, 'p', {
  書き込み可能: trueget: function() { 戻り値 456 }
});
// TypeError: 無効なプロパティ記述子。
// アクセサーと値または書き込み可能な属性の両方を指定することはできません

上記のコードで、「get」属性と「value」属性が同時に定義され、「writable」属性が「true」に設定されている場合、エラーが報告されます。

Object.defineProperty() および Object.defineProperties() パラメータのプロパティは、writableconfigurable、および enumerable のデフォルト値はすべて false です。

var obj = {};
Object.defineProperty(obj, 'foo', {});
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// 値: 未定義、
// 書き込み可能: false,
// 列挙可能: false,
// 設定可能: false
// }

上記のコードでは、obj.fooを定義する際に空の属性記述オブジェクトが使用されており、各メタ属性のデフォルト値が確認できます。

Object.prototype.propertyIsEnumerable()

インスタンス オブジェクトの propertyIsEnumerable() メソッドは、プロパティが通過可能かどうかを決定するブール値を返します。このメソッドはオブジェクト自体のプロパティを決定するためにのみ使用でき、継承されたプロパティに対しては常に「false」を返すことに注意してください。

var obj = {};
obj.p = 123;

obj.propertyIsEnumerable('p') // true
obj.propertyIsEnumerable('toString') // false

上記のコードでは、obj.p はトラバース可能であり、obj.toString は継承されたプロパティです。

メタ属性

プロパティオブジェクトの個々のプロパティは、プロパティを制御するプロパティと考えることができるため、「メタプロパティ」と呼ばれます。

価値

value 属性はターゲット属性の値です。

var obj = {};
obj.p = 123;

Object.getOwnPropertyDescriptor(obj, 'p').value
// 123

Object.defineProperty(obj, 'p', { 値: 246 });
obj.p // 246

上記のコードは、「value」属性を使用して「obj.p」を読み取るか書き換える例です。

書き込み可能

「writable」属性は、ターゲット属性の値を変更できるかどうかを決定するブール値です。

var obj = {};

Object.defineProperty(obj, 'a', {
  値: 37、
  書き込み可能: false
});

obj.a // 37
obj.a = 25;
obj.a // 37

上記のコードでは、「obj.a」の「writable」属性は「false」です。この場合、「obj.a」の値を変更しても効果はありません。

通常モードでは、「writable」を「false」に設定して属性に値を代入してもエラーは報告されず、警告なしに失敗するだけであることに注意してください。ただし、厳密モードでは、「a」属性に同じ値が再割り当てされた場合でも、エラーが報告されます。

'厳密を使用';
var obj = {};

Object.defineProperty(obj, 'a', {
  値: 37、
  書き込み可能: false
});

obj.a = 37;
// Uncaught TypeError: オブジェクトの読み取り専用プロパティ 'a' に割り当てることができません

上記のコードは厳密モードであり、「obj.a」への割り当てに対してエラーが報告されます。

プロトタイプ オブジェクトのプロパティの「writable」が「false」の場合、子オブジェクトはこのプロパティをカスタマイズできません。

var proto = Object.defineProperty({}, 'foo', {
  値: 'a'、
  書き込み可能: false
});

var obj = Object.create(proto);

obj.foo = 'b';
obj.foo // 'a'

上記のコードでは、proto はプロトタイプ オブジェクトであり、その foo プロパティは書き込み可能ではありません。 obj オブジェクトは proto を継承しており、この属性はカスタマイズできません。厳密モードでは、これもエラーをスローします。

ただし、属性説明オブジェクトをオーバーライドすることでこの制限を回避する回避策があります。その理由は、この場合、プロトタイプ チェーンが完全に無視されるためです。

var proto = Object.defineProperty({}, 'foo', {
  値: 'a'、
  書き込み可能: false
});

var obj = Object.create(proto);
Object.defineProperty(obj, 'foo', {
  値: 'b'
});

obj.foo // "b"

列挙可能

enumerable (通過可能性) は、ターゲット プロパティが通過可能かどうかを示すブール値を返します。

JavaScript の初期バージョンでは、「for...in」ループは「in」演算子に基づいていました。プロパティがオブジェクト独自のものであるか継承されたものであるかに関係なく、「in」演算子は「true」を返すことがわかっています。

var obj = {};
obj の 'toString' // true

上記のコードでは、toStringobj オブジェクト自体のプロパティではありませんが、in 演算子も true を返します。これにより、toString プロパティが for...in によってトラバースされます。 ループ。

これは明らかに無理があったため、後に「通過可能性」という概念が導入されました。また、「toString」などのインスタンス オブジェクトによって継承されるネイティブ プロパティは通過できないことも規定されているため、「for... in」ループの可用性が保証されます。 。

具体的には、属性の「enumerable」が「false」の場合、次の 3 つの操作では属性を取得できません。

  • for..in ループ
  • Object.keys メソッド
  • JSON.stringify メソッド

したがって、「enumerable」を使用して「秘密」プロパティを設定できます。

var obj = {};

Object.defineProperty(obj, 'x', {
  値: 123、
  列挙可能: false
});

obj.x // 123

for (obj の var キー) {
  コンソール.ログ(キー);
}
// 未定義

Object.keys(obj) // []
JSON.stringify(obj) // "{}"

上記のコードでは、「obj」の「enumerable」がその値です。

「for...in」ループには継承されたプロパティが含まれますが、「Object.keys」メソッドには継承されたプロパティが含まれないことに注意してください。オブジェクト自体のすべてのプロパティを取得する必要がある場合は、それが走査可能かどうかに関係なく、Object.getOwnPropertyNames メソッドを使用できます。

さらに、JSON.stringify メソッドは、enumerablefalse であるプロパティを除外しますが、これが悪用される可能性があります。オブジェクトの JSON 形式出力から特定のプロパティを除外したい場合は、これらのプロパティの enumerablefalse に設定できます。

構成可能

configurable(構成可能性) は、プロパティ記述オブジェクトを変更できるかどうかを決定するブール値を返します。つまり、configurable が false の場合、writable、enumerable、configurable は変更できません。

var obj = Object.defineProperty({}, 'p', {
  値: 1、
  書き込み可能: false、
  列挙可能: false、
  設定可能: false
});

Object.defineProperty(obj, 'p', {書き込み可能: true})
// TypeError: プロパティを再定義できません: p

Object.defineProperty(obj, 'p', {列挙可能: true})
// TypeError: プロパティを再定義できません: p

Object.defineProperty(obj, 'p', {構成可能: true})
// TypeError: プロパティを再定義できません: p

Object.defineProperty(obj, 'p', {値: 2})
// TypeError: プロパティを再定義できません: p

上記のコードでは、「obj.p」の「configurable」属性は「false」です。その後、writableenumerableconfigurable を変更すると、エラーが報告されました。

「writable」属性は、「false」が「true」に変更された場合にのみエラーを報告することに注意してください。「true」から「false」への変更は許可されます。

var obj = Object.defineProperty({}, 'p', {
  書き込み可能: true、
  設定可能: false
});

Object.defineProperty(obj, 'p', {書き込み可能: false})
// 変更が成功しました

value 属性の状況は特殊です。 「writable」と「configurable」のいずれかが「true」である限り、「value」の変更は許可されます。

var o1 = Object.defineProperty({}, 'p', {
  値: 1、
  書き込み可能: true、
  設定可能: false
});

Object.defineProperty(o1, 'p', {値: 2})
// 変更が成功しました

var o2 = Object.defineProperty({}, 'p', {
  値: 1、
  書き込み可能: false、
  構成可能: true
});

Object.defineProperty(o2, 'p', {値: 2})
// 変更が成功しました

さらに、writablefalse の場合、ターゲット属性は直接割り当てられ、エラーは報告されませんが、成功しません。

var obj = Object.defineProperty({}, 'p', {
  値: 1、
  書き込み可能: false、
  設定可能: false
});

obj.p = 2;
obj.p // 1

上記のコードでは、obj.pwritablefalse になっており、obj.p への直接代入は有効になりません。 strict モードの場合、エラーが報告されます。

ターゲット属性を削除できるかどうかは、構成可能性によって決まります。

var obj = Object.defineProperties({}, {
  p1: { 値: 1、設定可能: true }、
  p2: { 値: 2、設定可能: false }
});

obj.p1 を削除 // true
obj.p2 を削除 // false

obj.p1 // 未定義
obj.p2 // 2

上記のコードでは、「obj.p1」の「configurable」が「true」なので削除できますが、「obj.p2」は削除できません。

アクセサ

プロパティは直接定義するだけでなく、アクセサーを使用して定義することもできます。このうち、値を保存する関数は setter と呼ばれ、属性を使用してオブジェクトの set 属性を記述します。値を取得する関数は getter と呼ばれ、属性を使用してオブジェクトの get 属性を記述します。オブジェクト。

ターゲット属性にアクセサを定義すると、アクセス時に対応する関数が実行されます。この機能を使用すると、プロパティの読み取りおよび割り当て動作のカスタマイズなど、多くの高度な機能を実装できます。

var obj = Object.defineProperty({}, 'p', {
  取得: 関数 () {
    「ゲッター」を返します。
  }、
  セット: 関数 (値) {
    console.log('setter: ' + value);
  }
});

obj.p // "ゲッター"
obj.p = 123 // "セッター: 123"

上記のコードでは、「obj.p」は「get」プロパティと「set」プロパティを定義します。 obj.p が値を取得すると、get が呼び出され、値が割り当てられると、set が呼び出されます。

JavaScript には、アクセサーを作成する別の方法も用意されています。

//書き方2
var obj = {
  get p() {
    「ゲッター」を返します。
  }、
  set p() {
    console.log('setter: ' + value);
  }
};

属性 p の読み取りと代入の動作は上記の 2 つの書き方で同じですが、いくつかの微妙な違いがあります。最初の書き方では、属性 pconfigurableenumerable は両方とも false であるため、属性 p は通過できなくなります。属性 ptrueであるため、プロパティp` はトラバース可能です。実際の開発では、2の書き方の方がよく使われます。

値関数 get はパラメーターを受け入れることができず、値関数 set は 1 つのパラメーター (つまり、属性の値) のみを受け入れることができることに注意してください。

アクセサーは、プロパティの値がオブジェクトの内部データに依存する場合によく使用されます。

var obj ={
  $n: 5get next() { return this.$n++ },
  set next(n) {
    if (n >= this.$n) this.$n = n;
    else throw new Error('新しい値は現在の値より大きくなければなりません');
  }
};

obj.next // 5

obj.next = 10;
obj.next // 10

obj.next = 5;
// キャッチされないエラー: 新しい値は現在の値より大きくなければなりません

上記のコードでは、next 属性の storage 関数と value 関数は両方とも内部属性 $n に依存しています。

オブジェクトのコピー

場合によっては、あるオブジェクトのすべてのプロパティを別のオブジェクトにコピーする必要があります。これは、次のメソッドを使用して実現できます。

var extend = function (to, from) {
  for (fromvar プロパティ) {
    to[プロパティ] = from[プロパティ];
  }

  に戻る;
}

伸ばす({}、 {
  答え: 1
})
// {a:1}

上記のメソッドの問題は、アクセサーによって定義されたプロパティに遭遇した場合、値がコピーされるだけであることです。

伸ばす({}、 {
  get a() { return 1 }
})
// {a:1}

この問題を解決するには、Object.defineProperty メソッドを通じてプロパティをコピーします。

var extend = function (to, from) {
  for (fromvar プロパティ) {
    if (!from.hasOwnProperty(property)) 続行;
    Object.defineProperty(
      に、
      財産、
      Object.getOwnPropertyDescriptor(from, プロパティ)
    );
  }

  に戻る;
}

extend({}, { get a(){ return 1 } })
// { get a(){ return 1 } })

上記のコードでは、hasOwnProperty 行を使用して継承されたプロパティを除外しています。そうしないと、Object.getOwnPropertyDescriptor が継承されたプロパティのプロパティ説明オブジェクトを読み取れないため、エラーが報告される可能性があります。

コントロールオブジェクトのステータス

場合によっては、オブジェクトが変更されないように、オブジェクトの読み取りおよび書き込みステータスを凍結する必要があります。 JavaScript は 3 つのフリーズ メソッドを提供します。最も弱いメソッドは Object.preventExtensions、次に Object.seal、そして最も強いメソッドは Object.freeze です。

Object.preventExtensions()

Object.preventExtensions メソッドにより、オブジェクトに新しいプロパティを追加できなくなります。

var obj = 新しいオブジェクト();
Object.preventExtensions(obj);

Object.defineProperty(obj, 'p', {
  値: 'こんにちは'
});
// TypeError: property:p を定義できません。オブジェクトは拡張可能ではありません。

obj.p = 1;
obj.p // 未定義

上記のコードでは、「obj」オブジェクトが「Object.preventExtensions」を通過した後は、新しいプロパティを追加できません。

Object.isExtensible()

Object.isExtensible メソッドは、オブジェクトが Object.preventExtensions メソッドを使用しているかどうかを確認するために使用されます。つまり、オブジェクトにプロパティを追加できるかどうかを確認します。

var obj = 新しいオブジェクト();

Object.isExtensible(obj) // true
Object.preventExtensions(obj);
Object.isExtensible(obj) // false

上記のコードでは、obj オブジェクトで Object.preventExtensions メソッドを使用した後、Object.isExtensible メソッドを使用すると、新しいプロパティを追加できないことを示す false が返されます。

Object.seal()

Object.seal メソッドを使用すると、オブジェクトに新しいプロパティを追加したり、古いプロパティを削除したりすることができなくなります。

var obj = { p: 'こんにちは' };
オブジェクト.シール(obj);

obj.p を削除します。
obj.p // "こんにちは"

obj.x = 'ワールド';
obj.x // 未定義

上記のコードでは、obj オブジェクトが Object.seal メソッドを実行した後、新しいプロパティを追加したり、古いプロパティを削除したりすることはできません。

Object.seal は基本的に、プロパティ記述オブジェクトの configurable 属性を false に設定するため、プロパティ記述オブジェクトは変更できなくなります。

var obj = {
  p:「あ」
};

// シールメソッドの前
Object.getOwnPropertyDescriptor(obj, 'p')
// 物体 {
// 値: "a",
// 書き込み可能: true,
// 列挙可能: true,
// 設定可能: true
// }

オブジェクト.シール(obj);

//アフターシールメソッド
Object.getOwnPropertyDescriptor(obj, 'p')
// 物体 {
// 値: "a",
// 書き込み可能: true,
// 列挙可能: true,
// 設定可能: false
// }

Object.defineProperty(obj, 'p', {
  列挙可能: false
})
// TypeError: プロパティを再定義できません: p

上記のコードでは、Object.seal メソッドを使用した後、プロパティ記述オブジェクトの configurable プロパティが false になり、enumerable プロパティが変更されるとエラーが報告されます。

Object.seal は属性の追加または削除を禁止するだけであり、特定の属性の値の変更には影響しません。

var obj = { p: 'a' };
オブジェクト.シール(obj);
obj.p = 'b';
obj.p // 'b'

上記のコードでは、この時点では p 属性の書き込み可能性が writable によって決定されているため、 p 属性の value に対して Object.seal メソッドは無効です。

Object.isSealed()

Object.isSealed メソッドは、オブジェクトが Object.seal メソッドを使用しているかどうかを確認するために使用されます。

var obj = { p: 'a' };

オブジェクト.シール(obj);
Object.isSealed(obj) // true

このとき、Object.isExtensible メソッドも false を返します。

var obj = { p: 'a' };

オブジェクト.シール(obj);
Object.isExtensible(obj) // false

Object.freeze()

Object.freeze メソッドは、オブジェクトが新しいプロパティを追加したり、古いプロパティを削除したり、プロパティの値を変更したりできないようにして、オブジェクトを実際に定数にすることができます。

var obj = {
  p:「こんにちは」
};

オブジェクト.フリーズ(obj);

obj.p = '世界';
obj.p // "こんにちは"

obj.t = 'こんにちは';
obj.t // 未定義

obj.p を削除 // false
obj.p // "こんにちは"

上記のコードでは、obj オブジェクトに対して Object.freeze() を実行した後、プロパティの変更、プロパティの追加、およびプロパティの削除は無効になります。これらの操作はエラーを報告せず、ただ黙って失敗するだけです。厳密モードの場合、エラーが報告されます。

Object.isFrozen()

Object.isFrozen メソッドは、オブジェクトが Object.freeze メソッドを使用したかどうかを確認するために使用されます。

var obj = {
  p:「こんにちは」
};

オブジェクト.フリーズ(obj);
Object.isFrozen(obj) // true

Object.freeze メソッドを使用した後、Object.isSealedtrue を返し、Object.isExtensiblefalse を返します。

var obj = {
  p:「こんにちは」
};

オブジェクト.フリーズ(obj);

Object.isSealed(obj) // true
Object.isExtensible(obj) // false

Object.isFrozen の用途の 1 つは、オブジェクトのプロパティに値を割り当てる前に、オブジェクトが凍結されていないことを確認することです。

var obj = {
  p:「こんにちは」
};

オブジェクト.フリーズ(obj);

if (!Object.isFrozen(obj)) {
  obj.p = '世界';
}

上記のコードでは、「obj」が凍結されていないことを確認し、そのプロパティに値を割り当てた後、エラーは報告されません。

制限事項

上記の 3 つのメソッドには、オブジェクトの書き込み可能性をロックする抜け穴があります。プロトタイプ オブジェクトを変更することで、オブジェクトにプロパティを追加できます。

var obj = 新しいオブジェクト();
Object.preventExtensions(obj);

var proto = Object.getPrototypeOf(obj);
proto.t = 'こんにちは';
オブジェクト
// こんにちは

上記のコードでは、オブジェクト obj 自体に新しいプロパティを追加することはできませんが、そのプロトタイプ オブジェクトに新しいプロパティを追加することができ、それを obj で読み取ることができます。

解決策の 1 つは、「obj」のプロトタイプもフリーズすることです。

var obj = 新しいオブジェクト();
Object.preventExtensions(obj);

var proto = Object.getPrototypeOf(obj);
Object.preventExtensions(proto);

proto.t = 'こんにちは';
obj.t // 未定義

もう 1 つの制限は、属性値がオブジェクトの場合、上記のメソッドはその属性が指すオブジェクトのみを凍結でき、オブジェクト自体のコンテンツは凍結できないことです。

var obj = {
  フー: 1、
  バー: ['a', 'b']
};
オブジェクト.フリーズ(obj);

obj.bar.push('c');
obj.bar // ["a", "b", "c"]

上記のコードでは、「obj.bar」属性は配列を指します。「obj」オブジェクトが凍結された後は、このポインタは変更できません。つまり、他の値を指すことはできませんが、指す配列は変更できます。 。


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0