维护范围

时间:2013-04-11 21:25:20

标签: javascript jquery scope this

我有一个关于在对象中维护this范围的一般性问题。这是一段简化的代码片段。记下var that = this行以及我调用that.showMenu()的事件处理程序内部。

var MyObj = {
    init : function(target){
        this.$Target = $(target);
        this.$Menu = $(target).find('.menu');
        this.eventBindings();
    },
    eventBindings : function(){
        var that = this;
        this.$Target.on('click', '.anchor', function(e){
            e.preventDefault();
            that.showMenu();
            //some other code
        });
    },
    showMenu : function(){
        this.$Menu.show();
    }
};
MyObj.init('.myTarget')

代码应该有点自我解释。通常我会尝试在eventBindings()之外创建可重用的方法。我不断遇到的问题是通过thisMyObj引用到事件处理程序中,以便我可以调用this.showMenu()

为了克服这个障碍,我总是将this分配给一个名为that的变量,所以当我进一步向下范围时,我有一个参考。但我觉得这不是最好的方法......有人可以提出更好的选择吗?

3 个答案:

答案 0 :(得分:1)

你在做什么是最好的方法。在Javascript中this是动态范围的(绑定依赖于堆栈,即位于调用函数的位置),所有其他变量 - 都是静态范围的(绑定取决于代码中变量的静态位置)。

由于Javascript以特殊方式处理this,因此也不要以特殊的方式对待它。

您可以在函数中封装您现在正在执行的操作 - 许多库提供了这样的工具,通常称为“绑定”。但这不会改变真正发生的事情,只会隐藏它(并在执行此操作时耗尽一些资源)。这样的功能看起来有点像:

function whatever (functionToProcess, thisToFreeze) { 
   return function() {
       functionToProcess.apply(thisToFreeze, arguments); // apply is built in
   }
}

答案 1 :(得分:0)

继@ Pointy的评论,使用Function.prototype.bind

    onClick: function(e){
        e.preventDefault();
        this.showMenu();
        //some other code
    },
    eventBindings : function(){
        this.$Target.on('click', '.anchor', this.onClick.bind(this));
    },

答案 2 :(得分:0)

您可以将其作为事件数据传递:

this.$Target.on('click', '.anchor', {obj:this}, function(e){
    e.preventDefault();
    e.data.obj.showMenu();
    //some other code
});

或者将它存储在元素上,但是除了声明另外一个变量之外,两者都没有任何不同。