【问题标题】:How to call a constructor method of Parent class from child prototype in javascript?如何从javascript中的子原型调用Parent类的构造方法?
【发布时间】:2016-05-17 02:19:47
【问题描述】:

下面是代码sn-p,我在构造函数中定义了'run'方法,这与原型中定义的'eat'方法不同。我如何从从 A1 继承的 B1 原型访问这个“运行”方法。我的意图是覆盖 B1 中的“运行”方法,我可以在其中使用 A1 的现有“运行”方法。有什么方法可以实现吗?

function A1() {
	this.run = function() {
		return 'A1 runs';
	}
};
A1.prototype.eat = function() {
	return 'A1 eats';
};

function B1() {
	A1.call(this);
};
B1.prototype = Object.create(A1.prototype); //new A1();

B1.prototype.eat = function() {
	return A1.prototype.eat.call(this) + ',B1 also eats'; 
}

B1.prototype.run = function() {
	var parentRun = this.constructor.run();
	 var result = parentRun + ",B1 also runs";
	 return result; 
};


var b1 = new B1();
b1.eat(); // It will give 'A1 eats, B1 also eats', which is fine
b1.run(); // It will give 'A1 runs', where I want 'A1 runs, B1 also runs'.

编辑 1: 我更新了代码 sn-p,删除了 console.log 并从每个方法返回了字符串。

最初我没有对此进行研究。一些人提到它与this 重复,我已经通过相同的链接,但我的问题完全不同。我知道如何调用我为“吃”所做的父类原型的方法。

我的查询很简单,
有什么方法可以访问Parent类的构造方法('run'方法),而不是原型的方法('eat'方法)?

【问题讨论】:

  • 您不会从A1.prototype.run 返回任何内容以将其连接起来,并且您不会执行来自B1.prototype.run 的字符串连接结果的console.log
  • @Aprillion 请参阅Edit1。如果我仍然在某个地方犯错,请告诉我。

标签: javascript inheritance


【解决方案1】:

三个问题:

  1. A1 放置在实例上的 run 不会返回任何内容,因此调用它会产生 undefined

  2. A1run 放在实例 上,这意味着在您的b1 实例中,B1.prototype.run 已被run 遮挡,A1 直接分配给实例。

  3. this.constructor.run() 不是 A1 版本。

如果你把run放在A1.prototype上,你就可以做到:

function A1() {
}
A1.prototype.eat = function() {
    console.log('A1 eats');
};
A1.prototype.run = function() {
    return 'A1 runs';
};

function B1() {
    A1.call(this);
}
B1.prototype = Object.create(A1.prototype);

B1.prototype.run = function() {
    return A1.prototype.run.call(this) + ",B1 also runs";
};
var b1 = new B1();
console.log(b1.run());

这很丑,这就是为什么I wrote a script to automate supercalls back in the day,但这就是你在这个级别工作时的做法。

不过,现在,您会使用 ES2015 的 class 语法和 super 来代替,如果需要支持过时的 JavaScript 引擎,则使用 BabelTraceur 或类似方法进行转译:

class A1 {
    eat() {
        console.log("A1 eats");
    }
    run() {
        return "A1 runs";
    }
}

class B1 extends A1 {
    run() {
        return super.run() + ",B1 also runs";
    }
}

var b1 = new B1();
console.log(b1.run());

您的编辑说您希望run 出现在原型上,它必须由A1 分配,如下所示:

function A1() {
    this.run = function() {
        return 'A1 runs';
    };
}

这有点麻烦,但您仍然可以做到。由于我上面提到的原因,在实例上设置 run 会掩盖您的实例通常使用的 B1.prototype.run。所以要使用它,还要调用A1non-prototype run,你必须在实例上替换它。

因此,在B1 中定义B1run 比在B1.prototype 上更有意义,就像A1A1 中定义它一样,而不是在A1.prototype 中定义它:

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
        return A1run.call(this) + ",B1 also runs";
    };
}

活生生的例子:

function A1() {
    this.run = function() {
        return 'A1 runs';
    };
}
A1.prototype.eat = function() {
    console.log('A1 eats');
};

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
        return A1run.call(this) + ",B1 also runs";
    };
}
B1.prototype = Object.create(A1.prototype);

var b1 = new B1();
console.log(b1.run());

但如果你真的,真的希望它(至少部分)出现在B1.prototype

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
      return A1run.call(this) + B1.prototype.run.call(this);
    };
}
// ...
B1.prototype.run = function() {
    return ",B1 also runs";
};

活生生的例子:

function A1() {
    this.run = function() {
        return 'A1 runs';
    };
}
A1.prototype.eat = function() {
    console.log('A1 eats');
};

function B1() {
    var A1run;
    A1.call(this);
    A1run = this.run;
    this.run = function() {
        return A1run.call(this) + B1.prototype.run.call(this);
    };
}
B1.prototype = Object.create(A1.prototype);

B1.prototype.run = function() {
    return ",B1 also runs";
};
var b1 = new B1();
console.log(b1.run());

【讨论】:

  • 感谢您使用“类”的解决方案,但目前我不是在寻找 ES6 或与“类”兼容的东西。我也编辑了我的 sn-p 以澄清我的查询。你能帮我解决这个问题吗!
  • @DebajitMajumder:如果您需要A1run 直接放在实例上而不是通过原型,那么您必须在B1 中覆盖它。我已经添加到答案中以显示如何。
  • @t-j-crowder :太棒了,谢谢。 :) 还有一个疑问:虽然我同意这一点 - “在 B1 中定义 B1 的运行而不是在 B1.prototype 上是有意义的,就像 A1 在 A1 中定义它一样,而不是在 A1.prototype 上 ",但是有什么方法可以直接从 B1 的原型访问/调用 A1 的 run 方法,而不是在 B1 的构造函数中定义它!
  • @DebajitMajumder:不在B1.prototype.run,因为b1.run()调用了A1直接放在实例上的run。 B1 必须干预的唯一机会是 B1 函数本身,在构建过程中。请记住,“自己的”属性胜过继承的属性。
  • @t-j-crowder:哦,是的,明白了。感谢您的深入解释。
猜你喜欢
  • 2015-10-10
  • 1970-01-01
  • 2015-01-17
  • 2017-11-11
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 2012-01-22
  • 1970-01-01
相关资源
最近更新 更多