【问题标题】:Update prototype property in JavaScript在 JavaScript 中更新原型属性
【发布时间】:2012-06-11 12:12:07
【问题描述】:

我正在尝试实现原型继承,但我不理解它的行为。

考虑以下示例:

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 这是正确的,但是当我尝试更新实际发生的值时,它是在 yehuda 上创建一个新属性 sex

一种可能的解决方案是直接访问原型属性 (Object.getPrototypeOf(yehuda).sex = 'female'),但这意味着我需要知道对象所属的属性。

【问题讨论】:

  • 你知道,man.sex = 'male' 就足够了 :-)

标签: javascript jquery inheritance prototype


【解决方案1】:

使用原型的想法是,当您尝试访问对象上的属性时,解释器将首先尝试在给定对象上找到该属性。

如果在给定对象上找不到该属性,则解释器将尝试在对象的原型上找到它,依此类推,直到原型链以 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 答案。

编辑:我建议您不要尝试更改原型的值。这是因为许多对象可能具有相同的原型。更改原型上的任何值意味着更改将反映在依赖它的所有对象上。除非这是您想要实现的目标,否则我建议您在原型链上使用阴影属性。

注意:您可以删除对象的属性。如果您删除的属性正在遮蔽另一个属性,那么它会在您下次访问相同的属性名称时使用被遮蔽的属性。

【讨论】:

  • 你的解释中最重要的部分是有缺陷的。 because JavaScript is a dynamic language,真的吗?我想了解更多,因为我也不明白,而且“因为 JS 是一种动态语言”肯定没有帮助。
  • 由于 JavaScript 是一种动态语言,当您向对象添加新属性时它不会报错。在上述情况下,当您为对象yehuda 上的属性sex 赋值时,JavaScript 解释器会看到给定对象上不存在这样的属性。因此它会在对象yehuda 上创建一个名为sex 的新属性,即使给定属性确实存在于yehuda 的原型上。新的sex 属性隐藏了对象原型上的同名属性。这是否清楚你的想法?很高兴能提供帮助。
  • 我们可能需要在创建extendedObject 时添加object 结构的原型以及参数object。否则原型extendedObject不具备object原型函数如hasOwnPropertytoString
猜你喜欢
  • 1970-01-01
  • 2023-03-16
  • 2017-04-27
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多