1

我开始在 JavaScript 中定义类,我对关键字 有很多麻烦this

这是我想做的一个例子:

function MyMap() {

    this.map = new google.maps.Map(....);

    google.maps.event.addListener(this.map, 'idle', function() {
        this.mapIdle();    // PROBLEM: "this" undefined
    });

    this.mapIdle = function() {
        google.maps.event.addListener(marker, 'click', function() {
            $("button").click(function() {
                $.ajax({
                    success: function() {
                        this.map.clearInfoWindows(); // PROBLEM: "this" undefined
                    }
                });
            });
        });
    }
}

正如您在评论中看到的,在this这里不起作用,因为它在一个闭包中使用。

我已经开始使用以下解决方法

var that = this;
google.maps.event.addListener(this.map, 'idle', function() {
    that.mapIdle();
});

甚至你必须在你的回调函数周围定义一个回调函数(说真的!!)。

这是极其丑陋的,并不适用于任何地方。当我得到很多嵌套的 lambda 函数(如我给出的示例中)时,我不知道如何使用类属性。

最好和最正确的方法是什么?

4

4 回答 4

3

最简单的方法是定义一个self变量(或者that,如果您不介意非语义变量名称),如您已经提到的:

function MyMap() {
   var self = this;

   // in nested functions use self for the current instance of MyMap
}

请注意,您必须为添加到原型的方法再次执行此操作(如果它们使用嵌套函数):

MyMap.prototype.myMethod = function() {
   var self = this;
   // use self in nested functions
};

您还应该阅读该.bind()方法,注意它不适用于 IE <= 8。

您链接到的关于围绕回调定义回调的问题是解决一个不同的问题,即设置适当的闭包结构以允许嵌套在循环内的函数访问适当的循环计数器值。这与问题无关this。(并且可以在需要时轻松地与该self技术相结合。)

于 2012-04-03T22:22:18.710 回答
1

如果您使用的是 jQuery,$.proxy这很方便:

http://api.jquery.com/jQuery.proxy/

于 2012-04-03T22:08:29.173 回答
1

您可以将对象和函数分配给局部变量,然后将它们包含在回调函数的闭包中:

function MyMap() {

  var map = new google.maps.Map(....);

  var mapIdle = function() {
    google.maps.event.addListener(marker, 'click', function() {
      $("button").click(function() {
        $.ajax({
          success: function() {
            map.clearInfoWindows();
          }
        });
      });
    });
  };

  this.map = map;
  this.mapIdle = mapIdle; // Is this needed?

  google.maps.event.addListener(this.map, 'idle', function() {
    mapIdle();
  });

}
于 2012-04-03T22:12:35.023 回答
1

在 JavaScript 中,this每个函数调用都会重新分配。

这只是您在 JavaScript 中必须注意的事情。一开始可能会令人困惑,但是一旦您了解了一些简单的规则,它实际上就非常简单了。

如果是类似的方法调用myObj.doSomething(),那么this会自动设置为myObjinside of doSomething()

如果要this在进行函数调用时显式控制 的值,可以使用doSomething.apply()doSomething.call()来控制this函数内部设置的内容。这就是事件处理程序回调的作用。它们显式设置this为指向创建事件的对象(这非常有用)。您可以阅读有关MDN 的.apply()更多信息。.call()

如果你只是调用一个常规函数,那么this将被设置为在浏览器中是对象的全局window对象。

所有回调函数的值都会被this弄乱,因为每个函数调用都会发生变化this。由于您的事件处理程序是回调,而成功处理程序是 Ajax 函数中的回调,您应该期望this不会从周围的代码中保留 的值。有一些使用代理或绑定函数的变通方法,但通常this在闭包中捕获之前的值并使用类似var self = this;.

在您的情况下,当您想从事件处理程序外部访问this指针时,正确的做法是将其保存到您可以在事件处理程序中访问的局部变量中,甚至在事件中的 Ajax 调用中处理程序。没有更清洁的方法可以做到这一点。这样,您就可以访问this来自事件或 Ajax 调用的this指针以及来自调用对象的指针,如下所示:

    var self = this;
    self.mapIdle = function() {
        google.maps.event.addListener(marker, 'click', function() {
            $("button").click(function() {
                $.ajax({
                    success: function() {
                        self.map.clearInfoWindows(); // PROBLEM: "this" undefined
                    }
                });
            });
        });
    }
}
于 2012-04-03T23:56:03.493 回答