2012-04-03 47 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 
        } 
       }); 
      }); 
     }); 
    } 
}