[英]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.