我构建了一些基础PopupBuilder类,并希望在一些不同的用例中实现它。对于每种情况,我创建一个类扩展基类 所以:
function PopupBuilder () {
var _this = this;
this.buildPopup = function () {
var popup = $('<div>', {
id: "popup",
class: "full-page",
click: clickHandler});
} //works fine
function acceptChanges () {}
function clickHandler (event) { // works fine
console.log(_this); // _this doesn't overrides by child class _this. Should it?
acceptChanges(event); // doesn't overrides by child class function as well
}
}
function ToServerSender (text) {
var _this = this;
function acceptChanges (event) {
// send data to server
}
}
ToServerSender.prototype = new PopupBuilder();
var updateFile = new ToServerSender();
updateFile.buildPopup();
我创建了一个子类的实例,为什么我不能使用子类代码并覆盖/扩展基类? 我应该如何重写它将起作用的代码?
答案 0 :(得分:3)
您需要记住,OOP在JavaScript中的工作方式与类式OOP大不相同。
所以让我们分解一下:
var _this = this;
当在您发布的代码末尾调用new PopupBuilder()
构造函数时,会发生此分配。这里的this
指的是PopupBuilder
类型的对象,通过继承本质上是&#34;共享&#34;在ToServerSender
的所有实例中。每个ToServerSender
都没有自己的_this
副本。
function acceptChanges () {}
这只是PopupBuilder
构造函数中存在的函数。这不是一种方法。它不能通过在ToServerSender
构造函数中定义新的来覆盖它:
console.log(_this); // _this doesn't overrides by child class _this. Should it?
如上所述,这里的_this
指的是_this
的一个实例,它是在您调用PopupBuilder
构造函数时创建的,它在{的所有实例之间共享{1}}。
ToServerSender
这只是acceptChanges(event); // doesn't overrides by child class function as well
构造函数中acceptChanges
函数的闭包。它无法被覆盖。
<强> 1。使用可覆盖的方法。
您需要做的一件事是将方法分配给PopupBuilder
,以便子对象可以覆盖它们:
this
在这里,我们让构造函数为function PopupBuilder () {
var _this = this;
this.buildPopup = function () {} //works fine
this.acceptChanges = function () {}
this.clickHandler = function (event) {
console.log(this);
this.acceptChanges(event);
}
}
的属性分配函数,以便它们可以通过原型链继承并根据需要覆盖:
this
<强> 2。使用function ToServerSender (text) {
var _this = this;
// overrides prototype's .acceptchanges
this.acceptChanges = function (event) {
// send data to server
}
}
创建子类型的原型,而不是构造函数。
使用构造函数在子类型上创建原型有点过时了。 new way to do this是使用Object.create()
来创建父对象原型的副本:
Object.create
但这会留下ToServerSender.prototype = Object.create(PopupBuilder.prototype);
原型而没有在ToServerSender
构造函数中初始化的所有东西。这实际上是一件好事,因为PopupBuilder
构造函数正在创建一个私有变量的副本,这些变量将在现有的所有PopupBuilder
之间共享,可能会造成严重破坏。
解决这个问题的方法是......
第3。从子构造函数中调用父构造函数:
ToServerSenders
这里发生的是function ToServerSender(text) {
PopupBuilder.call(this);
var _this = this;
this.a = "hello";
//this class overrides acceptChanges from PopupBuilder
this.acceptChanges = function(event) {
// send data to server
console.log(1);
console.log(_this);
}
}
调用本身上的ToServerSender
构造函数,以便在该构造函数内创建PopupBuilder
时,它指的是_this
,而非共享ToServerSender
。这允许您在闭包中使用它并清除您遇到的一些问题。
所以这些是要记住的主要事项。我知道这有很多东西,但你使用的越多,它就越容易。
答案 1 :(得分:0)
您需要将功能附加到对象。
function PopupBuilder () {
var _this = this;
this.buildPopup = function () {} //works fine
this.acceptChanges = function() { console.log(2);}
this.clickHandler = function(event) { // works fine
console.log(_this); // _this doesn't overrides by child class _this. Should it?
//Look a the difference here: when you use _this.acceptChanges it prints 2 when you use this.acceptChanges() it prints 1 to the console.
this.acceptChanges(event); // doesn't overrides by child class function as well
}
}
function ToServerSender (text) {
var _this = this;
this.a = "hello";
//this class overrides acceptChanges from PopupBuilder
this.acceptChanges = function(event) {
// send data to server
console.log(1);
console.log(_this);
}
}
ToServerSender.prototype = new PopupBuilder();
var updateFile = new ToServerSender();
updateFile.buildPopup();
查看上面的代码,看看它是如何工作的。
在PopupBuilder
console.log中打印_this
时,它会在该范围内使用对this
的引用(包含旧acceptChanges
。但在ToServerSender
中范围已更改。此实例具有其他属性,并由该范围中的this
对象引用。此示例显示使用对此的引用与对象之间的区别。
旁注:当使用多个对象实例时,请使用函数引用来避免内存问题。
示例
this.clickHandler = clickHandlerPopupBuilder
function clickHandlerPopupBuilder(event) {
console.log(_this);
this.acceptChanges(event);
}