如何覆盖JS构造函数链的绑定?

时间:2013-12-05 17:48:19

标签: javascript prototypal-inheritance jquery late-binding constructor-chaining

我正在尝试在JavaScript中定义一个基类,它在创建时执行许多常用功能。该功能的一部分是创建一个组件并向该组件注册回调处理程序。

我遇到的问题是如何覆盖扩展我的基类的子类中用于该回调处理程序的函数。

具体而言,我有一个BasicPage组件,用于创建Table组件。 BasicPage还定义了一个默认的onRowClick函数,该函数将使用新创建的Table进行注册。

现在,我想创建一个PageWithSections组件,扩展BasicPage(通过call(..)语句)并覆盖onRowClick。问题是单击处理程序与表的注册发生在基类的构造函数中。在注册时,onRowClick尚未被覆盖,因此引用的是onRowClick的基类版本。

我做了一个说明问题的jsBin。

http://jsbin.com/uDEjuzeQ/9/edit

如果您按顺序点击每个框一次,我希望消息框显示为:

  

还没有消息;   行点击;   行点击; BasicPage onRowClicked;   行点击; PageWithSections onRowClicked

在构造基础对象期间,覆盖构造函数链中的函数并将重写函数绑定到某个函数的正确方法是什么?

更新 这个问题原始引用了一个原型链,但实际上原型并没有在这个例子中使用。

问题已更新,以反映这一点。这最终成为关于后期绑定的更多问题。

3 个答案:

答案 0 :(得分:1)

我看到的最大问题是您的_onRowClicked(传递给表格的回调)实际上并未在原型中定义。

您实际上并不是使用原型继承 - 您正在构造函数中定义方法,并从另一个构造函数中调用它们。

尝试重构代码,以便在BasicPage中定义BasicPage.prototype的某些默认行为(当前未对其进行引用/更改)。那时,使用原型继承的解决方案可能会突然变得明显。 :)

答案 1 :(得分:1)

以下是一些应该有效的代码:

var BasicPage = function(){
  this.name="BasicPage";
  document.body.onclick=this._getClick(this);
};
BasicPage.prototype._getClick=function(me){
  return function(e){
    console.log("target is:,",e.target);
    console.log("this is:",me.name);
  }
};

var PageWithSections = function(){
  //initialise parent and it's instance members
  BasicPage.call(this);
  //override name
  this.name="PageWithSections";
};
PageWithSections.prototype=Object.create(BasicPage.prototype);
PageWithSections.prototype.constructor=PageWithSections;

var sect = new PageWithSections();
document.body.click();

以下代码演示了如何在不复制和粘贴已有的BasicPage代码的情况下扩展onclick处理程序:

var BasicPage = function(){
  this.name="BasicPage";
  document.body.onclick=this._getClick(this);
};
BasicPage.prototype._getClick=function(me){
  return function(e){
    console.log("re used code from BasicPage");
    console.log("target is:,",e.target);
    console.log("this is:",me.name);
  }
};

var PageWithSections = function(){
  //initialise parent and it's instance members
  BasicPage.call(this);
  //override name
  this.name="PageWithSections";
};
//set prototype chain
PageWithSections.prototype=Object.create(BasicPage.prototype);
PageWithSections.prototype.constructor=PageWithSections;
//extend _getClick
PageWithSections.prototype._getClick=function(me){
  var fn=BasicPage.prototype._getClick.call(me,me);
  return function(e){
    //do BasicPage click code
    fn(e);
    //extended code
    console.log("with a little extra from PageWithSections");
  };
};


var sect = new PageWithSections();
document.body.click();

有关原型和构造函数here的更多信息。介绍应该非常有用,如果你有时间,我建议阅读所有内容,以便对JS原型有一个很好的理解。

答案 2 :(得分:0)

我的同事提出了一个可能的解决方案。正如@cloudfeet所说,它不是原型,但它确实有效。

基本上他将绑定设置为不同的实例函数,而调用 _onRowClick函数,该函数在执行时会被覆盖。

http://jsbin.com/uDEjuzeQ/16/edit