テキストを入力する前に、次の 2 つの質問に答えてみましょう。
質問1:
let obj = {
name: "ikun",
};
let obj1 = {
fun: "xiaoheizi",
};
Object.setPrototypeOf(obj1, obj);
obj1.name = "cai";
console.log(obj1);
/*输出结果为:
{fun: 'xiaoheizi', name: 'cai'}
*/
質問2:
let obj = {
// name: "ikun",
};
Object.defineProperty(obj, "name", {
writable: false,
value: "ikun",
});
let obj1 = {
fun: "xiaoheizi",
};
Object.setPrototypeOf(obj1, obj);
obj1.name = "cai";
console.log(obj1);
//{fun: 'xiaoheizi'}
なぜ?なぜこれが起こるのですか? 勉強を続けましょう:
属性の設定とマスキング
オブジェクトにプロパティを設定することは、新しいプロパティを追加したり、既存のプロパティの値を変更したりするだけではありません。それでは、プロセス全体を見ていきましょう。
myObject.foo =" bar ";
- my0object オブジェクトに foo という名前の通常のデータ アクセス プロパティが含まれている場合、この割り当てステートメントは既存のプロパティ値のみを変更します。
- foo が my0object に直接存在しない場合、[[ Get ]] 操作と同様に、[[ Prototype ]] チェーンがトラバースされます。
- プロトタイプ チェーンに foo が見つからない場合、foo は my0object に直接追加されます。
ただし、割り当てステートメント myObject . foo = " bar " は、
foo がプロトタイプ チェーンの上位に存在する場合、多少異なる動作をします (おそらく予期せず)。それについては後で説明します。
プロパティ名 foo が my0bject と my0bject の [[ Prototype ]] チェーンの両方にある場合、マスキングが発生します。myObject.foo は常にプロトタイプ チェーンの最下位の foo プロパティを選択するため、my0object に含まれる foo プロパティは、プロトタイプ チェーンの上位にあるすべての foo プロパティを隠します。
シールドは私たちが思っているよりも複雑です。myObject.foo="bar" のときに foo が myObject に直接存在せず、プロトタイプ チェーンの上位層に存在する場合に発生する 3 つの状況を分析してみましょう。
- [[ Prototype ]] チェーンの上位層に foo という名前の通常のデータ アクセス プロパティがあり、それが読み取り専用 (書き込み可能: false) としてマークされていない場合、foo という名前の新しいプロパティが myObject に直接追加されます。 、これはシールド プロパティです。
- [[ Prototype ]] チェーンに foo が存在するが、読み取り専用 ( writable : false ) としてマークされている場合、my0object で既存のプロパティを変更したり、シールドされたプロパティを作成したりすることはできません。厳密モードで実行すると、コードはエラーをスローします。それ以外の場合、この割り当てステートメントは無視されます。つまり、シールドは発生しません。
- [[ Prototype ]] チェーンに foo が存在し、それが seter である場合、seter を呼び出す必要があります。foo は myObject に追加 (またはシャドウイング) されず、foo セッターも再定義されません。
ほとんどの開発者は、[[ Prototype ]] チェーンの既存のプロパティ ([[ Put ]]) に値を割り当てると、ブロックが確実にトリガーされると想定していますが、ご覧のとおり、3 つのケース (第一種)はこんな感じです。
2 番目と 3 番目のケースで foo もマスクしたい場合は、= 演算子を使用してキーを割り当てることはできませんが、Object.defineProperty(...) を使用して foo を myObject に追加します。
2 番目のケースはおそらく最も驚くべきものです。読み取り専用のプロパティは、[[ Prototype ]] ダウンチェーンが同じ名前のプロパティを暗黙的に作成 (シールド) するのを防ぎます。これは主にクラスのプロパティの継承をシミュレートするためのもの. プロトタイプチェーンの上位層にある foo を親クラスのプロパティと見なすことができ, myObject に継承 (コピー) されます. myObject も読み取り専用なので作成できません。ただし、同様の継承コピーは実際には発生しないことに注意することが重要です。
他のオブジェクトには読み取り専用の foo があるため、 myObject オブジェクトに foo プロパティを持たないのは少し奇妙に思えます。さらに奇妙なのは、この制限が = 割り当てにのみ存在し、 Object.defineProperty を使用しても影響を受けないことです。私たちは開発するときに注意を払う必要があります。