“this”关键字的继承和问题

时间:2011-10-20 14:52:08

标签: javascript oop inheritance this prototypal-inheritance

我正在构建一个相当复杂的Web应用程序,该应用程序以用户进行初始选择的主菜单开始。这是我第一次尝试在JavaScript中使用继承的真正的OOP方法,并且我遇到了第一个问题,“this”关键字没有提到我期望它。我猜这是我的OOP /继承方法更广泛问题的结果,所以我希望得到一个答案,它不仅告诉我如何解决这个问题,而且还提供了更深入的反馈和建议。< / p>

我只会发布JS代码,因为我不认为HTML是相关的,但我必须在必要时发布它。

以下代码定义了主类Select。然后它创建一个名为Select的{​​{1}}的子类(查看代码的末尾)。在SelectNum中,我试图覆盖SelectNum的{​​{1}}方法,但不完全 - 我想首先调用super(Select)方法,然后运行一些额外的代码。但是当这个子类的mouseover方法运行时,我立即得到以下错误:

“未捕获的TypeError:无法调用未定义的方法'stop'”

基本上,Select未定义。

首先,我使用的是O'Reilly的JavaScript:The Definitive Guide:

mouseover

我的代码:

this.shine

修改 Raynos的回应奏效了。 function inherit(p) { if (Object.create){ // If Object.create() is defined... return Object.create(p); // then just use it. } function f() {}; // Define a dummy constructor function. f.prototype = p; // Set its prototype property to p. return new f(); // Use f() to create an "heir" of p. } 不再抛出错误,并运行了正确的代码。但是,我实际上需要创建一个名为Select = function(el){ return this.init(el); } Select.prototype = { init: function(el){ var that = this; this.el = el; this.shine = el.children('.selectShine'); el.hover(function(){ that.mouseover(); },function(){ that.mouseout(); }); return this; }, mouseover: function(){ this.shine.stop().animate({opacity:.35},200); }, mouseout: function(){ var that = this; this.shine.stop().animate({opacity:.25},200); } } //Sub-classes SelectNum = function(el){ this.init(el); this.sup = inherit(Select.prototype); //allows access to super's original methods even when overwritten in this subclass return this; } SelectNum.prototype = inherit(Select.prototype); SelectNum.prototype.mouseover = function(){ this.sup.mouseover(); //call super's method... but this breaks down //do some other stuff } 的{​​{1}}子类。与覆盖其超类“this.sup.mouseover()方法的SelectNum不同,SelectLevel不需要覆盖SelectNum的{​​{1}}方法:

mouseover()

使用此代码,只需连续调用SelectLevel方法。我相信这是因为SelectNum现在绑定到mouseover()对象,因此SelectLevel = function(el){ this.init(el); this.sup = inherit(SelectNum.prototype); //allows access to super's original methods even when overwritten in this subclass for(var k in this.sup){ this.sup[k] = this.sup[k].bind(this); } } SelectLevel.prototype = inherit(SelectNum.prototype); mouseover()行中的this始终引用SelectLevel,所以它一直在呼唤自己。

如果我删除this.sup中的this.sup.mouseover()绑定,则会收到错误SelectNum。似乎SelectNum被连续调用,在原型链中的每个对象上调用this.sup[k] = this.sup[k].bind(this);方法。当它达到SelectLevel时,就会抛出此错误,因为Uncaught TypeError: Cannot call method 'mouseover' of undefined当然没有this.sup.mouseover()属性。

似乎我可以通过删除mouseover中的Object绑定,然后将Object包装在首先检查sup属性的if语句中来解决此问题在调用this.sup[k] = this.sup[k].bind(this);方法之前:SelectLevel,但这确实感觉不对。

最终,我认为我遗漏了一些关于如何在JavaScript中进行子类化的基础知识。虽然这些特定问题的解决方案确实阐明了原型继承如何在JS中起作用,但我认为我需要在更广泛的层面上有更好的理解。

1 个答案:

答案 0 :(得分:2)

this.sup.mouseover();

调用对象.mouseover上的this.sup方法。你想要的是

this.sup.mouseover.call(this)

您不希望在this.sup上调用它,而是想在this上调用它。

如果这对屁股很痛苦,那么你可以在构造函数中执行以下操作

this.sup = inherit(Select.prototype);
for (var k in this.sup) {
  if (typeof this.sup[k] === "function") {
    this.sup[k] = this.sup[k].bind(this);
  }
}

这基本上意味着覆盖具有相同功能的每个方法,但将this的值硬绑定到您期望/想要的值。