1

我是 JS 新手,我知道函数是声明“类类”结构的方式。我正在尝试做这样的事情:

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. 我做错了吗?有没有更好的方法以更优雅的方式实现这样的目标?
4

1 回答 1

4

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

this在 Javascript 中引用调用函数的对象。因此,如果您有一个对象的属性恰好被分配了函数的值,并且您调用该属性,则this指针将引用该对象。它不引用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 之后),我几乎只将它用于绑定功能。

于 2013-06-26T03:31:25.780 回答