将新的 属性 分配给具有冻结原型的空对象
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 = {}
将创建新的自己的 属性 特定对象,不会为原型的 属性 分配新值,但它可能会进行查找对于 属性 检查可写性,在这种情况下它将 运行 冻结为对象。我以前不知道这个。
What I don't get is why can't I assign to specificObject
if its prototype is frozen?
因为属性属性是继承的。是的,很奇怪。
如果冻结一个对象,它会将所有数据属性的 [[writable]]
属性设置为 false
。
如果您分配给一个对象 属性,但对象上不存在 属性,它会在原型上查找它 - 它可能被定义为 [=35] =] 那里。当此查找将 return 并说存在该名称的 属性 但它不可写时,您的分配将失败(并在严格模式下抛出)。
你能做些什么来解决这个问题?
- 使用
Object.defineProperty
代替赋值,它不检查原型
- 或者类似的,使用
Object.create
的第二个参数创建自己的属性
- 仅在分配给
specificObject
后才冻结 defaults
。
为什么我不能将新属性分配给具有冻结原型的非冻结对象:
没有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 = {}
将创建新的自己的 属性 特定对象,不会为原型的 属性 分配新值,但它可能会进行查找对于 属性 检查可写性,在这种情况下它将 运行 冻结为对象。我以前不知道这个。
What I don't get is why can't I assign to
specificObject
if its prototype is frozen?
因为属性属性是继承的。是的,很奇怪。
如果冻结一个对象,它会将所有数据属性的 [[writable]]
属性设置为 false
。
如果您分配给一个对象 属性,但对象上不存在 属性,它会在原型上查找它 - 它可能被定义为 [=35] =] 那里。当此查找将 return 并说存在该名称的 属性 但它不可写时,您的分配将失败(并在严格模式下抛出)。
你能做些什么来解决这个问题?
- 使用
Object.defineProperty
代替赋值,它不检查原型 - 或者类似的,使用
Object.create
的第二个参数创建自己的属性 - 仅在分配给
specificObject
后才冻结defaults
。