在 Javascript 中重新定义原型与附加到原型

Redefining prototype vs appending to prototype in Javascript

从这里开始:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Performance considerations

function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype = {
  getName: function() {
    return this.name;
  },
  getMessage: function() {
    return this.message;
  }
};

However, redefining the prototype is not recommended. The following example instead appends to the existing prototype:

function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype.getName = function() {
  return this.name;
};
MyObject.prototype.getMessage = function() {
  return this.message;
};

以上引用和代码来自给定的 link.
我想了解第一个代码如何提示我们正在重新定义原型,而第二个代码如何提示我们正在附加原型?

上面几段代码中什么代表重定义什么代表追加?

第一个代码 MyObject.prototype = { ... } 建议重新定义原型,因为我们将全新的对象设置为 MyObject.prototype

但第二个代码建议附加,因为它仅通过对象的特定键(getNamegetMessage)分配函数。

当您重新定义 prototype 对象时,您正在创建一个全新的对象,而不是保留现有原型及其属性,这是不可取的。

如果我们重新定义原型对象,它会打破继承层次。特别是 instanceofObject.prototype.isPrototypeOf 将无法按预期工作。

让我们举个例子,展示一个简单的继承层次结构,ChildClassOneChildClassTwo 继承自 ParentClass

在第一种情况下,继承被打破,因为 prototype 被一个全新的对象覆盖,该对象擦除已经存在的所有信息,而不是附加到从 Object.create 接收到的原型打电话。

在第二种情况下,它按预期工作,因为原型没有被替换:

function ParentClass(param) {
  this.param = param;
}
ParentClass.prototype.getParam = function() {
  return this.param;
}

function ChildClassOne(param, name, message) {
  ParentClass.call(param);
  this.name = name.toString();
  this.message = message.toString();
}
//Inheriting through prototype
ChildClassOne.prototype = Object.create(ParentClass.prototype);
ChildClassOne.constructor = ChildClassOne;

//Prototype completely overriden, destroying the hierarchy
ChildClassOne.prototype = {
  getName: function() {
    return this.name;
  },
  getMessage: function() {
    return this.message;
  }
};

//the instanceof and isPrototypeOf is broken
const child1 = new ChildClassOne("bazz", "foo", "bar");
console.log(child1 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child1));
console.log(ChildClassOne.prototype instanceof ParentClass)

function ChildClassTwo(param, name, message) {
  ParentClass.call(param);
  this.name = name.toString();
  this.message = message.toString();
}

//Inheriting through prototype
ChildClassTwo.prototype = Object.create(ParentClass.prototype);
ChildClassTwo.constructor = ChildClassTwo;

//Preserving the heirarchy information, by appending to existing prototype
ChildClassTwo.prototype.getName = function() {
  return this.name;
};
ChildClassTwo.prototype.getMessage = function() {
  return this.message;
}

//Works as expected
const child2 = new ChildClassTwo("bazz", "foo", "bar");
console.log(child2 instanceof ParentClass);
console.log(ParentClass.prototype.isPrototypeOf(child2));
console.log(ChildClassTwo.prototype instanceof ParentClass)