【问题标题】:How to manipulate properties of the object prototype?如何操作对象原型的属性?
【发布时间】:2018-08-20 17:33:08
【问题描述】:

我正在尝试执行以下操作:

function SomeFunctionConstructor() {
   this.someMainVariable = "someValue";
   this.manipulatePrototype = () => {
     this.someProtoVariable = "some new value";
   }
}

SomeFunctionConstructor.prototype.someProtoVariable = "Some proto value";


var someInstance = new SomeFunctionConstructor();

现在,如果我 console.log(someInstance),它会打印:

{
  someMainVariable: 'someValue',
  manipulatePrototype: [Function] 
}

现在,当我执行someInstance.manipulatePrototype() 然后console.log(someInstance) 时,它会打印:

{
  someMainVariable: 'someValue',
  manipulatePrototype: [Function],
  someProtoVariable: 'some new value' 
}

为什么它直接在实例上创建一个新的someProtoVariable,而不是在原型上更新someProtoVariable? :(

【问题讨论】:

  • 因为 JavaScript 对象属性分配总是这样工作的。它是语言设计的基本部分。如果它的工作方式不同,事情会很奇怪。
  • this 中的操作原型与 this 之外的完全相同
  • @Pointy 嗯,据我所知,当我们访问对象上的属性时,它首先检查该对象上是否存在直接属性,如果没有,则在原型链中查找该属性.如果它在原型链中找到一个,它将对其进行操作,如果找不到,将直接在对象上创建一个新属性。不是吗?
  • 嗯,你看到它发生在你正在使用的代码中,对吧?你的亲身经历还不够吗?它在语言规范中,但阅读起来非常复杂。

标签: javascript prototype ecmascript-5 function-constructor


【解决方案1】:

如果你真的想修改对象原型的属性,你可以直接通过构造函数引用原型:

SomeConstructor.prototype.property = newValue;

或在实例上使用Object.getPrototypeOf()

Object.getPrototypeOf(someInstance).property = newValue;

现在,一般来说事情会变得有点复杂,因为一个实例的原型链中可能有多个对象。在这种情况下,您可能需要什么取决于您的应用程序。

请注意,更改原型上的属性值将具有使该属性在所有实例上具有新值的效果。

您可以在原型中添加setter 函数来自动执行此操作:

Object.defineProperty(SomeConstructor.prototype, "property", {
  value: someInitialValue,
  set: function(value) {
    Object.getPrototypeOf(this)["@property"] = value;
  },
  get: function() {
    return Object.getPrototypeOf(this)["@property"];
  }
});

它使用另一个名为“@property”的原型属性(可以是任何名称,或者更好的是Symbol 实例)来存储“property”的表观值。有了这个,

someInstance.property = newValue;

将调用 setter 函数并更新原型上的“@property”值。

【讨论】:

  • 请注意,这样做会有点奇怪,并且广泛使用此策略的系统可能会出现许多意外行为。
【解决方案2】:

我认为您在实例和原型之间感到困惑。并且实例无法通过设计超越对象原型。如果发生这种情况,那么每个实例都将能够破坏原型链并影响从该原型构建的所有其他实例

如果您打印 someInstance.someProtoVariable 而不调用操作原型,那么您将获得旧值。

之后您将获得新值。
this.someProtoVariable 确实覆盖了实例的默认值,但没有覆盖原型本身

您可以在此处阅读有关原型的更多信息 Inheritance_and_the_prototype_chain

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    相关资源
    最近更新 更多