2013-04-11 79 views
3

我有一个关于在一个对象中维护this的范围的一般性问题。这里有一个简单的代码片段。请注意0​​一行,并在事件处理程序中呼叫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()之外创建可重用的方法。我不断遇到的问题是通过this,这将参考MyObj到事件处理程序,所以我可以拨打this.showMenu()

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

+0

对我来说看起来很好,但'那是一个可怕的名字。考虑一些更具描述性的内容,比如'outerScope'。 – 2013-04-11 21:27:23

+0

另请参阅函数原型上的[.bind()'方法](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind)。 – Pointy 2013-04-11 21:28:03

+0

@RobertHarvey尽管如此,多年来这种'这个'是如何被普遍使用的,这不是很有趣吗? ;) – summea 2013-04-11 21:53:50

回答

1

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

而且由于Javascript以特殊的方式对待this,所以不要以特殊的方式对待它。

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

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

太棒了 - 感谢您提供的信息。我会更多地了解绑定,但一般的共识是,我使用的方法是可以接受的,所以我不会试图强调它太多。 – Syon 2013-04-11 21:58:56

0

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

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

你可以在把它作为事件数据:

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

或将它储存的元素,但也不是真的有什么不同的是外面声明另一个变量一样你是。