如何操纵对象原型的属性?

时间:2018-08-20 17:33:08

标签: javascript prototype ecmascript-5 function-constructor

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

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? :(

2 个答案:

答案 0 :(得分:2)

如果您确实要修改对象原型的属性,则可以直接通过构造函数引用原型:

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”值。

答案 1 :(得分:1)

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

如果您打印出someInstance.someProtoVariable而没有调用invokePrototype,那么您将获得旧值。

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

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

相关问题