我正在尝试实现原型继承,但我不理解它的行为。
考虑以下示例:
var config = {
writable: true,
enumerable: true,
configurable: true
};
var defineProperty = function( obj, name, value ) {
config.value = value;
Object.defineProperty( obj, name, config );
}
var man = Object.create( null );
defineProperty( man, 'sex', 'male' );
var yehuda = Object.create( man );
defineProperty( yehuda, 'firstName', 'Yehuda' );
defineProperty( yehuda, 'lastName', 'Katz' );
当我访问yehuda.sex
时,返回male
这是正确的,但当我尝试更新实际发生的值时,就会在{{1}上创建新属性sex
}。
一种可能的解决方案是直接访问prototype属性(yehuda
),但这意味着我需要知道对象所属的属性。
答案 0 :(得分:0)
使用原型的想法是,当您尝试访问对象上的属性时,解释器将首先尝试在给定对象上找到该属性。
如果在给定对象上找不到该属性,则解释器将尝试在对象的原型上找到它,依此类推,直到原型链在null
结束。
如果找不到该属性,则解释器返回undefined
。否则返回属性值。
在您访问属性sex
的情况下,在对象上找不到它,但在对象的原型上找到它。因此它返回male
。
然后,当您为sex
分配新值时,它会在给定对象上创建一个新属性,而不是更改对象原型上的属性,因为JavaScript是一种动态语言。
这很好,因为新值会影响旧值。这就是原型继承的工作方式。
如果您明确要更新原型上的属性而不是给定对象,我建议您按如下方式在对象上创建属性:
function defineProperty(object, name, value) {
Object.defineProperty(object, name, {
value: value,
writable: true,
enumerable: true
});
}
function extendObject(object) {
var extendedObject = Object.create(object);
Object.keys(object).forEach(function (key) {
Object.defineProperty(extendedObject, key, {
set: function (value) {
object[key] = value;
},
enumerable: true
});
});
return extendedObject;
}
var man = Object.create(null);
defineProperty(man, "sex", "male");
var yehuda = extendObject(man);
defineProperty(yehuda, "firstName", "Yehuda");
defineProperty(yehuda, "lastName", "Katz");
这应该可以解决您的问题。要了解有关原型继承的更多信息,请阅读this回答。
编辑:我建议您不要尝试更改原型的值。这是因为许多对象可能具有相同的原型。更改原型上的任何值意味着更改将根据它反映在所有对象上。除非那是你想要实现的目标,否则我建议你在原型链上使用阴影属性。
注意:您可以删除对象的属性。如果您删除的属性是遮蔽另一个属性,则下次访问相同的属性名时将使用shadowed属性。