JS原型继承的意外结果

时间:2016-01-28 21:18:32

标签: javascript inheritance prototype

我有一个基类,如:

Stage.js:

function Stage(name) {
  this.my_name = name;
}

Stage.prototype.name = function() {
  return this.my_name;
}

module.exports = Stage;

并行:

var Stage = require("./Stage");

ParallelStage.prototype = Stage.prototype;

ParallelStage.prototype.execute = function() {
  console.log("+++ Executing stage " + this.name()+ " in parallel...");
  return this;
}

function ParallelStage(name) {
  Stage.call(this,name);
  return this;
}

module.exports = ParallelStage;

和Serial.js:

var Stage = require("./Stage");

SerialStage.prototype = Stage.prototype;

SerialStage.prototype.execute = function() {
  console.log("+++ Executing stage " + this.name()+ " in serial...");
  return this;
}

function SerialStage(name) {
  Stage.call(this,name);
  return this;
}

module.exports = SerialStage;

但是当我跑步时:

var Parallel = require ("./ParallelStage");
var Serial = require ("./SerialStage");

var parallel = new Parallel("Extraction");
parallel.execute();

我得到以下输出:

+++ Executing stage Extraction in serial...

我显然遗漏了一些关于javascript和原型继承的基本知识。有人能告诉我我在这里失踪的东西吗?我期待它显示并行执行阶段而不是串行...

4 个答案:

答案 0 :(得分:0)

您已将serialStageParallelStage的原型设置为Stage.prototype,因此现在您基本上使用所有三种方法的相同原型对象

当您向该原型写入内容时,它会覆盖任何可能具有相同名称的内容,例如

var Stage = function Stage() {}

ParallelStage.prototype = Stage.prototype; // set to Stage.prototype
ParallelStage.prototype.execute = function() {} 
// ^ you've attached an "execute" method to the Stage.prototype object


SerialStage.prototype = Stage.prototype; // set to the same Stage.prototype
SerialStage.prototype.execute = function() {}
// ^ you've just overwritten the "execute" function in Stage.prototype

您可以使用Object.createObject.assign和其他一些解决方案来创建原型对象的副本,以便每次都不会覆盖它的属性,但这种情况会失败首先继承它的目的。

答案 1 :(得分:0)

为了正确继承原型,你必须使用

SerialStage.prototype

致电时

Stage.prototype

您释放ParallelStage.prototype = Object.create(Stage.prototype); 对象,因为它引用了ParallelStage.prototype = Object.create(Stage.prototype); ,因此您的上一个继承对象始终覆盖原型的属性和方法。 因此,编辑代码并更改继承方式

<img onclick="myFunction()"/>
<script>
   var clickCounter = 0;
   var turnNum = 1;
   function myFunction () {
      clickCounter++;
      if (clickCounter == turnNum) {
         // do stuff
         turnNum++;
         clickCounter = 0;
      }
   }
</script>

Content-Type

答案 2 :(得分:0)

当你这样做时:

load('data2013.RData')

你没有创建基本原型的副本 - 它是一个赋值,就像它指向现有对象的任何其他赋值一样。因此,不是给SerialStage.prototype = Stage.prototype; ParallelStage提供独特的原型,而是为两个构造函数重用相同的原型。当你分配了执行方法时,你已经覆盖了现有的一次,而没有创建一个新的。

快速简便的解决方法是:

SerialStage

ParallelStage.prototype = new Stage();

这会为每个原型创建一个新对象,然后您可以将这些方法放在上面。原型委托将确保属性查找上升到原型链。

答案 3 :(得分:0)

问题是如何在以下行中使用Stage的原型:

ParallelStage.prototype = Stage.prototype

ParallelStage.prototype现在只是指向Stage.prototype的指针。修改它时,您将使用Stage原型替换所有对象的父函数。

出现您的具体问题是因为在Stage.js和Parallel.js之后执行了Serial.js;它对Stage.prototype的更改是最后一项,对StageSerialStageParallelStage类型的任何对象都有效。

从父级继承原型(或正确方法之一)的正确方法是使用以下方法:

Child.prototype = Object.create(Parent.prototype)

更改您的代码以使用此模式,您应该获得您之后的行为。