我正在使用John Resig为simple javascript inheritance提供的优秀javascript课程,而且我有一点麻烦地解决与'this'关键字相关的一些变量范围问题。
我的扩展课程看起来有点像这样
var EUNode = Class.extend({
// Methods
//-------------------------------------------------------------------------------
init : function(){
this.div = this.createDiv();
this.canDoStuff = true;
this.div.addEventListener(touchstart, this.touchStartHandler, false);
},
// Create Div
//-------------------------------------------------------------------------------
createDiv : function(){
// code to create a DIV element, add some classes and do some
// other useful stuff
},
touchStartHandler : function(event){
// In here, 'this' refers to the div element, so the
// following condition doesn't work
if(this.canDoStuff){
// do some stuff
}
}
});
我需要能够从touchStartEventHandler
内部引用EUNode实例,所以我尝试了以下
var EUNode = Class.extend({
// Methods
//-------------------------------------------------------------------------------
init : function(){
this._super();
// Store a reference to 'this' globally
self = this;
self.div = this.createDiv();
self.canDoStuff = true;
self.div.addEventListener(touchstart, self.touchStartHandler, false);
},
touchStartHandler : function(event){
if(self.canDoStuff){
// Now I can do stuff, but 'self' is now a global variable
// which isn't what I want. If there's more than one instance
// of EUNode, 'self' references the newest instance.
}
}
});
所以我陷入了困境。似乎为了限制全局“自我”的范围,我需要使用“this”关键字,但“this”意味着事件处理程序中的其他内容。有什么提示吗?
答案 0 :(得分:2)
是的,全局变量很糟糕(一般情况下)。正如您自己注意到的那样,如果您有两个EUNode实例,那么您已经遇到了麻烦,因为最后一个实例会覆盖全局self
。
你也使touchStartHandler
依赖于某个全局变量,这个函数的整个工作可能不再那么清楚了。
只需在正确的背景下致电touchStartHandler
:
init : function(){
var self = this; // <- local `self`
this.div = this.createDiv();
this.canDoStuff = true;
// pass a closure, making `self` available inside the function
this.div.addEventListener(touchstart, function(event) {
self.touchStartHandler(event);
}, false);
},
在支持ECMAScript 5的浏览器中,您还可以使用.bind()
[docs](请参阅其他浏览器的实现链接)来绑定元素this
应该参考:
this.div.addEventListener(touchstart, this.touchStartHandler.bind(this), false);
答案 1 :(得分:1)
当您建立事件处理程序时,只需在匿名函数中将调用包装为“touchStartHandler()”,以便通过类的相应实例调用它。
换句话说:
var boundHandler = function(event) { yourInstance.touchStartHandler(event); };
然后可以使用函数“boundHandler”来处理事件,并且将始终使用引用正确对象的this
来设置实际代码。
在较新的浏览器中还有一个名为“.bind()”的功能可以让你做同样的事情。
答案 2 :(得分:1)
而不是
self.div.addEventListener(touchstart, self.touchStartHandler, false);
尝试
self.div.addEventListener(touchstart, function(event) { self.touchStartHandler(event) }, false);
答案 3 :(得分:0)
self.touchStartHandler.bind(self)