2013-09-25 69 views
1

我想通過以下way-我怎樣才能調用JavaScript的匿名函數

function a() 
    { 
     this.memb = 10; 
    } 

    a.prototype.hide_member = function(id){ 
     alert(id); 
    } 

    a.prototype.show_member = function(){ 
     setTimeout('this.hide_member(this.memb)', 2000); //Problem 1 
     setTimeout(this.hide_member(this.memb), 2000); //Problem 2 
     setTimeout(alert(this.memb), 2000); //Problem 3 
     this.memb++; 
    } 

    var obj = new a(); 
    obj.show_member(); 

這裏訪問的匿名函數對象的成員函數的類slibing功能,問題1 -是代碼在被賦予什麼合適的時間究竟執行,意味着剛過2000毫秒,但它顯示2000年以後毫秒以下錯誤 -

Uncaught TypeError: Object [object global] has no method 'hide_member' 
(anonymous function) 

問題2 -的代碼是前ecuting,但它執行的代碼解析後,意味着2000毫秒而不是之後。

問題3 -相同的問題問題2

我在這裏獲得關於這3個問題的混亂。由於

+0

FWIW:將字符串傳遞到'setTimeout'或'setInterval'幾乎永遠不是最佳實踐。 –

回答

4

幾件事情是怎麼回事:

在此代碼:

setTimeout(this.hide_member(this.memb), 2000); 

立即調用this.hide_member,並通過其返回值放入setTimeout。這與foo(bar())完全相同,您在呼叫bar並將其返回值傳遞到foo

您需要將函數傳遞到setTimeout,然後從該函數中調用成員函數。請注意,在函數內部,this會有所不同,所以你必須記得:

a.prototype.show_member = function(){ 
    var self = this, 
     memb_to_hide = this.memb; 
    setTimeout(function() { 
     self.hide_member(memb_to_hide); 
    }, 2000); 
    this.memb++; 
} 

請注意,我還記得的this.memb舊值的函數中使用。

另一種方式來做到這一點是ES5's Function#bind,但它需要在瀏覽器的JavaScript引擎有(或已加載的「ES5墊片」,爲bind是shimmable功能):

a.prototype.show_member = function(){ 
    setTimeout(this.hide_member.bind(this, this.memb), 2000); 
    this.memb++; 
} 

Function#bind返回一個函數,該函數在被調用時將使用您在第一個參數中給出的值作爲this(然後傳遞任何更多參數)來調用原始函數。在這種情況下,我們沒有必須記住舊的值this.memb,因爲我們已經將舊值傳遞到bind


附註:您正在依靠自動分號插入的恐怖。我不建議這樣做,在你的報表的兩端供給分號,例如:

a.prototype.mumble = function() { 
    /*...*/ 
}; // <=== Note the ; 
+0

對於早期的錯誤抱歉,不會抓住'this.memb'的原始值在匿名函數中使用。 –

+0

謝謝,還有一點我無法得到,如果問題1中的第一個參數是單引號傳入的,這將是字符串,因此它如何執行。我猜測它會通過將代碼放在該函數中自動爲它創建一個匿名函數。我對嗎? – CodeCrypt

+0

@CodeCrypt,我認爲''setInterval'在內部使用'eval'。 –

0

試試這個:

a.prototype.show_member = function(){ 
    var self = this; 
    setTimeout('self.hide_member(self.memb)', 2000); //Problem 1 
    setTimeout(function() { self.hide_member(self.memb) }, 2000); //Problem 2 
    setTimeout(function() { alert(self.memb) }, 2000); //Problem 3 
    this.memb++; 
} 
+0

請注意,在所有三種情況下,將使用'memb'的** new **值。 –

1

是代碼是在被賦予什麼合適的時間究竟執行,意味着剛過2000毫秒,但它在2000年後MS

顯示以下錯誤

錯誤是自我解釋:this指的是全局對象而不是a類的實例。爲了避免這種情況,你必須參考保存到該實例的上下文:

a.prototype.show_member = function(){ 
    var self = this; //self refers to the instance 
    setTimeout('self.hide_member(self.memb)', 2000); 
    this.memb++; 
} 

的代碼執行,但它執行的代碼解析後,意味着2000毫秒而不是之後。

它解析後執行(要當show_member是所謂的最後一行是執行更清晰),因爲它是一個函數調用:

setTimeout(this.hide_member(this.memb), 2000); 

setTimeout需要一個字符串或函數爲了正確執行,你在這裏執行的是執行函數並返回一個值(在這種情況下沒有任何值,因此它是undefined),它將在2000 ms後由setTimeout執行。致undefined的結果是什麼?一個錯誤。第三種情況下的問題完全一樣。

注意: 強調的是傳遞一個字符串setTimeout是EVAL的一種形式,它應該避免這一點很重要;您可以改爲傳遞匿名函數:

a.prototype.show_member = function(){ 
    var self = this; //self refers to the instance 
    setTimeout(function() { 
     self.hide_member(self.memb); 
    }, 2000); 
    this.memb++; 
} 
相關問題