简体   繁体   English

更新JavaScript中的原型属性

[英]Update prototype property in JavaScript

I'm trying to implement prototypal inheritance but I'm not understanding it's behavior. 我正在尝试实现原型继承,但我不了解它的行为。

Consider the following example: 考虑以下示例:

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' );

When I access to yehuda.sex returns male which is correct, but when I try to update the value what actually happens it's the creation of a new property sex on yehuda . 当我访问yehuda.sex返回的是正确的male ,但是当我尝试更新该值时,实际发生的是在yehuda上创建新的属性sex

One possible solution is to access directly the prototype property ( Object.getPrototypeOf(yehuda).sex = 'female' ) but that implies that I need to know the property to which object belongs. 一种可能的解决方案是直接访问原型属性( Object.getPrototypeOf(yehuda).sex = 'female' ),但这意味着我需要知道对象所属的属性。

The idea of using prototypes is that when you try to access a property on an object the interpreter will first try to find that property on the given object. 使用原型的想法是,当您尝试访问对象上的属性时,解释器将首先尝试在给定对象上找到该属性。

If the property is not found on the given object then the interpreter will try to find it on the object's prototype and so on until the prototype chain ends in null . 如果在给定对象上找不到该属性,则解释器将尝试在对象的原型上找到它,依此类推,直到原型链以null

If the property is not found the interpreter returns undefined . 如果找不到该属性,则解释器返回undefined Otherwise it returns the property value. 否则,它将返回属性值。

In your case when you are accessing the property sex it's not found on the object but it is found on the object's prototype. 在您的情况下,当您访问属性sex它不在对象上找到,但在对象的原型上找到了。 Hence it returns male . 因此,它返回male

Then when you assign a new value to sex it creates a new property on the given object instead of changing the property on the object's prototype because JavaScript is a dynamic language. 然后,当您为sex分配新值时,由于JavaScript是一种动态语言,因此它会在给定对象上创建新属性,而不是更改对象原型上的属性。

This is fine since the new value shadows the old value. 这很好,因为新值会覆盖旧值。 That's the way prototypal inheritance works. 这就是原型继承的工作方式。

If you explicitly want to update the property on the prototype instead of the given object I suggest you create propeties on your objects as follows: 如果您明确想要更新原型的属性而不是给定的对象,我建议您按如下方式在对象上创建属性:

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 should solve your problem. 这应该可以解决您的问题。 To know more about prototypal inheritance read this answer. 要了解有关原型继承的更多信息,请阅读答案。

Edit: I suggest you do not try to change the values of the prototype. 编辑:我建议您不要尝试更改原型的值。 This is because many objects may have the same prototype. 这是因为许多对象可能具有相同的原型。 Changing any value on the prototype means that the change will be reflected on all the objects depending on it. 更改原型上的任何值意味着更改将反映在所有依赖于它的对象上。 Unless that is what you want to achieve I suggest you make do with shadowing properties on the prototypal chain. 除非那是您要实现的目标,否则我建议您使用原型链上的阴影属性。

Note: You can delete properties on objects. 注意:您可以删除对象的属性。 If the property you deleted was shadowing another property then it will shadowed property will be used the next time you access the same property name. 如果您删除的属性正在遮盖另一个属性,则它将被遮盖的属性将在您下次访问相同的属性名称时使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM