Javascript OOP:绑定方法到事件处理程序

时间:2013-06-26 03:22:04

标签: javascript oop this

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

1 个答案:

答案 0 :(得分:4)

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

Javascript中的

this引用了调用该函数的对象。因此,如果您的对象具有恰好被赋予函数值的属性,并且您调用该属性,则this指针将引用该对象。它没有引用创建函数的任何this,也没有引用函数本身。

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

在事件处理程序的情况下,处理程序函数(在纯Javascript中,忽略jQuery)被分配给DOM元素,因此它从该元素调用,因此this指向DOM元素。 / p>

在上面的示例中使用局部变量(如game)意味着您创建的函数(“闭包”)将“关闭”该变量,捕获该位置范围内任何变量的值功能已定义。除 this之外的任何变量。因此,您的解决方法是处理此问题的一种非常常见的方法。

处理这个问题的另一种常见方法是使用像Underscore.js这样的库,它有一个名为bind的函数,可以执行一些高阶函数魔法,以确保this总是指向什么你想要的。

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

出于这个原因,Underscore.js是我最喜欢的Javascript库之一(在jQuery之后),我几乎专门用于绑定函数。