2013-06-26 27 views
1

我是JS的新手,我理解函数是声明“class like”结构的方法。 我试图做这样的事情:Javascript OOP:绑定方法到事件处理程序

function Game() { 
    // Class stuff 

    this.handleClick = function(e) { 
    alert(e); 
    } 

    // Bind event to method previously defined 
    $('#board').bind('click', function(e) { 
    this.handleClick(e);    // <--- THIS IS THE PROBLEMATIC LINE 
    }); 
} 

现在,如果在 “问题的行” 我写:

handleClick(e) 

我得到Uncaught ReferenceError: handleClick is not defined

相反,如果我写:

this.handleClick(e); 

我得到Uncaught TypeError: Object #<HTMLCanvasElement> has no method 'handleClick'

不过呢,如果我这样做:

function Game() { 
    // Class stuff 

    this.handleClick = function(e) { 
    alert(e); 
    } 

    var game = this;     // <--- I ASSIGN this TO board 
    // Bind event to method previously defined 
    $('#board').bind('click', function(e) { 
    game.handleClick(e);    // <--- THIS WORKS!! WHY???? 
    }); 
} 

它的工作原理!?!?!

我的问题是:

  1. 这为什么会发生这样?我知道this可能会有问题,但为什么将它分配给变量会改变它呢?
  2. 我做错了吗?有没有更好的方式以更优雅的方式实现这样的事情?
+1

'this'取决于**你如何调用一个函数。在你的情况下,'this'是DOM元素。 – elclanrs

+0

好的,但为什么当我将它分配给一个变量它改变了它的值? – leo

+0

因为它失去了它的特殊含义,并且简单地存储了这个任务在分配时的情况。 –

回答

4

您在Javascript的闭包实现中找到了一个空洞。 (如果你不知道什么是闭包,请不要担心。)

this在Javascript中引用调用函数的对象。因此,如果您有一个物体碰巧被分配了函数的值,并且您调用该属性,则指针将引用该对象。它没有引用任何this函数创建的地方,也没有引用函数本身。

var object = {}; 
object.myfunc = function() { console.log(this); } //<-- this will refer to object 
object.myfunc(); 

在事件处理程序,该处理程序功能的情况下(在纯JavaScript,忽略jQuery的)被分配到DOM元素,所以它被从该元件,并因此this点的DOM元素调用。

在上例中使用局部变量(如game)意味着您创建的函数(“闭包”)将围绕该变量“关闭”,捕获函数所在位置的任何变量值定义。任何变量,除了this。所以你的解决方法是处理这个问题的一种非常常见的方式。

来处理这将是使用像Underscore.js一个库,它有一个名为bind功能做了一些高阶功能神奇,以确保this总是指向你想要的另一种常见的方式。

$('board').bind('click', _.bind(function(e) { 
    this.handleClick(e); 
}, this)); 

为此,Underscore.js是我最喜欢的JavaScript库(jQuery的之后)之一,我用它几乎完全是为绑定功能。

+2

你也可以在当前所有的浏览器中使用本地的'Function.prototype.bind'。 – elclanrs

+0

没有“洞”,因为这不是一个变量! – bfavaretto

相关问题