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