4

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

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

具体来说,我有一个BasicPage创建组件的Table组件。还定义了一个使用新创建的注册的BasicPage默认函数。onRowClickTable

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

我制作了一个 jsBin 来说明这个问题。

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

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

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

在构造基础对象期间覆盖构造函数链上的函数并将被覆盖的函数绑定到某些东西的正确方法是什么?

更新 此问题最初引用了原型链,但实际上原型并未在此示例中实际使用。

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

4

3 回答 3

1

The biggest issue I see is that your _onRowClicked (the callback you pass into the Table) is not actually defined in a prototype anywhere.

You are not actually using prototypical inheritance - you are defining the methods inside the constructor, and calling one constructor from another.

Try refactoring your code such that some of the default behaviour for BasicPage is defined in BasicPage.prototype (which is currently not referenced/altered at all). At that point, a solution that uses prototypical inheritance might suddenly become obvious. :)

于 2013-12-05T18:07:19.170 回答
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();

更多关于原型和构造函数的信息在这里。介绍应该非常有帮助,如果您有时间,我建议您阅读所有内容以更好地理解 JS 原型。

于 2013-12-05T23:48:41.017 回答
0

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

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

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

于 2013-12-05T19:03:40.970 回答