簡體   English   中英

將新屬性分配給具有凍結原型的空對象

[英]Assign new property to empty object which has frozen prototype

為什么我不能為具有凍結原型的非凍結對象分配新屬性:

在沒有 Object.freeze 的情況下工作:

'use strict'
//This object will be prototype of next objects
var defaults = {
  name: 'def name', 
  sections: {
    1: {
      secName: 'def sec name'
    }
  }
};

//So we have an empty object with prototype set to our default object.
var specificObject = Object.create(defaults);


specificObject.sections = {};
console.log(specificObject.hasOwnProperty('sections')); //true

specificObject.sections['1'] = Object.create(defaults.sections['1']);

上面的代碼按預期工作,但我想確保不會意外更改默認值。 所以我想凍結我的默認對象:

'use strict'
//This object will be prototype of next objects
var defaults = {
  name: 'def name', 
  sections: {
    1: {
      secName: 'def sec name'
    }
  }
};

//!!!!!!!!!!!!
Object.freeze(defaults);

//So we have an empty object with prototype set to our default object.
var specificObject = Object.create(defaults);

//TypeError: Cannot assign to read only property 'sections' of #<Object>
specificObject.sections = {};
console.log(specificObject.hasOwnProperty('sections')); //true

specificObject.sections['1'] = Object.create(defaults.sections['1']);

我不明白的是,如果其原型被凍結,為什么我不能分配給 specificObject?

//編輯:注意特定對象沒有被凍結:

'use strict'
//This object will be prototype of next objects
var protoObj = {a: 1, o: {}};
Object.freeze(protoObj);

console.log(Object.isFrozen(protoObj)); //true

var n = Object.create(protoObj);
console.log(Object.isFrozen(n)); //false

我的理解是specificObject.sections指向它的原型,這是defaults ,它是凍結對象。 您定義了一個新對象{}但您嘗試將其分配給defaults.sections SpecificObject.sections正好指向那里。

如果您在 specificObject 上創建新的ownProperty它將起作用:

'use strict'
//This object will be prototype of next objects
var defaults = {
  name: 'def name',
  sections: {
    1: {
      secName: 'def sec name'
    }
  }
};

//!!!!!!!!!!!!
Object.freeze(defaults);

//So we have an empty object with prototype set to our default object.
var specificObject = Object.create(defaults);

// this will create new property
Object.defineProperty(specificObject, 'sections',{
    enumerable: true,
    writable: true,
    configurable: true,
    value: {}
});
console.log(specificObject.hasOwnProperty('sections')); //true

specificObject.sections['1'] = Object.create(defaults.sections['1']);

解釋:

如果您嘗試訪問obj.prop = val則 javascript 會查看obj自己的屬性,如果未找到,則它會查看obj的原型自己的屬性。 如果在那里找到,那么它/嘗試將val分配給/查找該屬性。 如果在那里找不到,那么它會嘗試查看obj的原型的原型等等。 如果在prototype樹中找不到prop ,那么它會在obj上創建新的自己的屬性並分配val

因此,如果在原型上找到prop並且它被凍結,你會得到類型錯誤。 希望它帶來一些啟發。:)

編輯:

正如@KubaWyrostek specificObj.sections = {}正確指出的那樣,將創建特定對象的新屬性,不會為原型的屬性分配新值,但它可能會查找屬性以檢查可寫性,在這種情況下它會碰到凍結的物體。 我之前不知道這件事。

我不明白的是,如果其原型被凍結,為什么我不能分配給specificObject

因為屬性屬性是繼承的。 是的,這很奇怪。

如果您凍結一個對象,它會將所有數據屬性的[[writable]]屬性設置為false

如果您分配給一個對象屬性,但該屬性在該對象上不存在,它將在原型上查找它 - 它可能在那里被定義為 setter。 當此查找返回並說有該名稱的屬性但不可寫時,您的賦值將失敗(並在嚴格模式下拋出)。

對此你能做些什么?

  • 使用Object.defineProperty而不是賦值,它不檢查原型
  • 或者類似的,使用Object.create的第二個參數來創建自己的屬性
  • 僅在您分配給specificObject后凍結defaults

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM