我应该如何在包含其他javascript对象的javascript对象中处理'this'?

时间:2011-06-25 13:29:07

标签: javascript oop this

我正在使用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”意味着事件处理程序中的其他内容。有什么提示吗?

4 个答案:

答案 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)