我正在构建一个相当复杂的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中起作用,但我认为我需要在更广泛的层面上有更好的理解。
答案 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
的值硬绑定到您期望/想要的值。