我正在用 JavaScript 构建一个多源音频播放器,我的目标是编写几个扩展基类的提供程序类(用于 Youtube、Soundcloud 等),因此每个提供程序都将具有相同的方法和属性,但我可以为每个提供商自定义它们。
这是一个简化的示例。
基类如下所示:
function Player_Provider(slug) {
this.slug = slug;
console.log("Player_Provider init: " + this.slug);
};
Player_Provider.prototype.loadUrl = function(url) {
console.log("provider "+this.slug+" - load URL: " + url);
};
我为提供者“扩展”了这个类;例如:
function Player_Provider_Youtube() {
Player_Provider.call(this, 'youtube');
}
Player_Provider_Youtube.prototype = Object.create(Player_Provider.prototype); //inherit methods
Player_Provider_Youtube.prototype.constructor = Player_Provider_Youtube; //fix constructor
Player_Provider_Youtube.prototype.loadUrl = function(url) {
Player_Provider.prototype.loadUrl(url);
}
然后我像这样注册它:
var providers = [];
providers.youtube = new Player_Provider_Youtube();
providers.youtube.loadUrl("https://www.youtube.com/watch?v=5SIQPfeUTtg");
控制台输出:
Player_Provider init: youtube
provider undefined - load URL: https://www.youtube.com/watch?v=5SIQPfeUTtg
如您所见,控制台输出:
"provider undefined - load URL..."
当我希望它输出时:
"provider youtube - load URL..."
这里的想法是,在提供程序的每个函数中(每次都会重写基类中的函数),我会首先调用“父”函数,至少输出如下所示的控制台消息;并最终运行一些代码 - 本着尽可能拥有最干净的代码的想法。
我对 PHP 更熟悉,这是我第一次尝试使用 JavaScript 做这类事情。
你会如何做到这一点以及为什么我的变量未定义?
最佳答案
在 ES5 及更早版本中,这是一个痛苦。您使用 call
或 apply
,正如您所发现的,它确实很冗长。
Player_Provider_Youtube.prototype.loadUrl = function(url) {
Player_Provider.prototype.loadUrl.call(this, url);
// ------------------------------^^^^^^^^^^^
}
我发现这已经够痛苦了,我写了一个库来处理它( here ),但它现在已经过时了。
但是,在 2017 年,你不再这样做了;相反,您使用 ES2015 的 class
语法和转译(使用类似 Babel 的内容),因此它可以在较旧的 JavaScript 引擎上运行:
class Parent {
method() {
console.log("Parent method");
}
}
class Child extends Parent {
method() {
console.log("Child method");
super.method();
}
}
new Child().method();
它会为你处理所有令人讨厌的管道问题。它仍然是 ES2015 之前相同的原型(prototype)继承 + 构造函数,只是语法更简单。 (并且实现了一些我们无法使用旧语法完成的事情。)
关于javascript - JavaScript 中的继承 : How can I call the object parent?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43523543/