2012-06-08 26 views
8

varsayalım pencere setInterval geçmek:Ben bir işlev a sahip Nasıl "Bu"

function a() { 
    this.b = 1; 
    this.set = setInterval(function() {console.log(this.b);}, 200); 
} 

Yani a.set() çağrıldığında anonim işlev çağrılır. Ancak, bu işlev, fonksiyonun pencere nesnesine yönlendirildiği zaman bu şekilde çalışmayacaktır. Ayrıca, a.b'yi birden çok örneği olabileceğinden kullanmak da iyi bir fikir değildir.

Bu sorun için iyi bir çözüm nedir?

+0

neden "apply" veya "call" kullanmıyorsunuz https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply – Deeptechtons

+0

@Deeptechtons - Sanırım 'uygulamak' veya 'call', bu problem için herhangi bir kullanımdır, ancak belki de bir cevapta aklında ne olduğunu açıklayabilir misiniz? – nnnnnn

+0

@nnnnnn Soru kesinlikle "İçeriğin içeriklerini nasıl değiştirebilirim" sorusu için bir aday. Hangi appy kullanarak çözülür, veya arayın. Ancak bu dava için aşırı bir olasılık olabilir. – Deeptechtons

cevap

16

mağazası this bir referans:

function a() { 
    var self = this; 
    self.b = 1; 
    self.set = setInterval(function() {console.log(self.b);}, 200); 
} 

anonim fonksiyonu setInterval geçmek de ihtiva kapsamında, diğer bir deyişle, function a() herhangi bir lokal değişkenler herhangi bir değişken erişimi vardır. JS kapanışlarının büyüsü, a() tamamlandıktan sonra bile bu değişkenleri canlı tutar ve her bir a() çağrısının kendi kapanması olur.

+0

Evet, bunun gibi örnekleri gördüm ama bu beni kafam karıştıran şey. "A" nın, olayın 200 msn tetiklenmesinden önce biteceğini varsayalım, değişken kendiliğin o anda yok edilmesi gerektiği görünüyor. Eğer değilse, o zaman ne zaman imha edilecek? aralık temizlendikten sonra? – NSF

+0

Cevabımda bahsettiğim gibi, bir iç işlev, içerme işlevi bittikten sonra _even işlevini içeren değişkenlere erişebilir. Bu durumda 'setInterval 'içsel işleve bir referans tutmaya devam eder, böylece a()' bittikten sonra bile onu çağırabilir; Aralığın temizlenmesine kadar referansın canlı kalacağı ve değişkenlerin hayatta kalacağı. JS'nin tek bir iş parçacığı üzerinde çalıştığı için, aralığın tetiklenmesinden önce a() 'nin _definitely_ bitişi (aralığın ne kadar kısa olursa olsun) olacağına dikkat edin. Daha fazla bilgi için Google "JavaScript kapanışları". – nnnnnn

+0

anlamlıdır. Teşekkürler. – NSF

2

this referans numaranızı başka bir değişkendeki kaydet, daha sonra window -kartı ile geçersiz kılmayın. Daha sonra, başladığınız nesneyi referans almak için bu değişkeni kullanabilirsiniz. Senin durumunda

function a() { 
    this.b = 1; 
    var that = this; 
    this.set = setInterval(function() {console.log(that.b);}, 200); 
} 
0

, sadece yapabilirsiniz:

function a() { 
    var _this = this; 
    this.b = 1; 
    this.set = setInterval(function() { 
     console.log(_this.b); 
    }, 200); 
} 

Normalde biz de bir yardımcı yöntemini Function.prototype.bindthis referans düzeltme zorunda olabilir.

4

çoğu zaman gerçekte ardışık yöntem için bu bağlam geçiş yapmak istediğiniz beri bu, en temiz çözüm olacaktır çağırır:

// store scope reference for our delegating method 
    var that = this; 
    setInterval(function() { 
     // this would be changed here because of method scope, 
     // but we still have a reference to that 
     OURMETHODNAME.call(that); 
    }, 200); 
3

şimdi ES6 olduğundan, biz burada başka bir yanıt gerektiğini düşünüyorum :

bir ok işlevi kullanın: bir this bağlama sahip olmayan, zıt Normal işlevlerine,

function a() { 
    this.b = 1; 
    this.set = setInterval(() => {console.log(this.b);}, 200); 
} 

ok fonksiyonlarını onların kendi. Bu, dış this erişiminiz olduğu anlamına gelir.

+1

ES6, sözdizimi neredeyse hiçbir şey için azaltmadı! Teşekkürler! – HoldOffHunger