2012-04-03 13 views
1

我开始在JavaScript中定义类,并且我在关键字this中遇到了很多麻烦。在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不会在这里工作,因为它是用来封闭内。

我已经开始使用workarounds,如:

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

甚至,你必须define a callback function在你的回调函数(严重!!)。

这是极度丑陋并且无处不在。当我得到很多嵌套的lambda函数(如我给出的例子)时,我不知道如何使用类属性。

什么是最好和最正确的方法来做到这一点?

+2

作为一个侧面说明,你可能会有所帮助:充分了解' this'关键字](http://net.tutsplus.com/tutorials/javascript-ajax/fully-understanding-the-this-keyword/)。 – 2012-04-03 22:04:50

+3

另外,作为一个附注,你很少会发现在Javascript中做任何事情的“最终方式” - 它不是那种语言。 – nrabinowitz 2012-04-03 22:06:01

回答

3

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

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() method读了起来,并指出它不适用于IE < = 8。

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

+0

我做这样的事情。我有时称之为“公共”来与“私人”范围/子对象形成对比。 – Umbrella 2012-04-03 23:00:56

+0

这工作得很好,非常感谢。 JavaScript有时候可能会很痛苦... – 2012-04-04 17:45:34

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(); 
    }); 

} 
1

在JavaScript中,this被重新分配给每一个函数调用。

这只是你必须在JavaScript中知道的东西。起初可能会让人困惑,但一旦你知道了一些简单的规则,它实际上很简单。

如果是方法调用如myObj.doSomething(),则this将自动设置为doSomething()内部的myObj

如果你想要做一个函数调用时明确控制的this值,你可以使用doSomething.apply()doSomething.call()控制什么this设置为函数内。这就是事件处理函数的回调函数。他们明确地设置this指向创建事件的对象(这非常有用)。您可以在MDN上阅读关于.apply().call()的更多信息。

如果您只是调用常规函数,那么将this设置为浏览器中的全局对象是window对象。因为每个函数调用都会改变this。由于您的事件处理程序是回调函数,并且成功处理程序是Ajax函数中的回调函数,因此您应该期望this的值不会被周围的代码保留。使用代理或绑定功能可以解决问题,但通常在闭包中捕获之前的this值并且只需从var self = this;之类的地方访问即可。

在你的情况下,当你想访问从事件处理程序之外的this指针,正确的做法是只将它保存到一个局部变量,你将在事件处理程序,甚至在Ajax调用必须访问即在事件处理程序中。没有更干净的方法来做到这一点。这样,您可以访问无论从事件或Ajax调用的this指针,从您的通话对象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 
        } 
       }); 
      }); 
     }); 
    } 
}