2011-04-02 57 views
12

讓我們看看這段JavaScript代碼:的setTimeout回調說法

function Person(name) { 
    this.name = name; 
} 

Person.prototype.showName = function() { 
    alert(this.name); 
} 


var mike = new Person("mike"); 
//mike.showName(); 

window.name = "window"; 

我不明白的

setTimeout(mike.showName(), 5000); 

行爲之間的區別
setTimeout(function(){ 
    mike.showName(); 
}, 5000); 

爲什麼行爲不同?它真的讓我困惑。謝謝。

+1

您注意到了哪些性能差異? – 2011-04-02 00:15:02

+5

我相當肯定OP在他表示「表現」時意味着「行爲」。 – 2011-04-02 00:22:29

回答

45

你的問題真有在所有無關setTimeout。你只需要理解函數調用和函數引用之間的區別。

考慮這四個分配:

var one = function() { mike.showName(); }; 
var two = mike.showName; 
var three = mike.showName(); 
var four = (function() { mike.showName(); })(); 

前兩個對函數的參考分配給它們各自的變量。然而,最後兩個函數調用函數(這是parens的用途),並將它們的返回值分配給左側的變量值。

如何此涉及的setTimeout:

setTimeout函數期望作爲其第一個參數參考於函數時,所以無論是onetwo以上將是正確的,但threefour不會。然而,重要的是要注意,嚴格來說,它不是錯誤將函數的返回值傳遞給setTimeout,但您會經常看到這一點。

這是完全正常的,例如:

function makeTimeoutFunc(param) { 
    return function() { 
     // does something with param 
    } 
} 

setTimeout(makeTimeoutFunc(), 5000); 

它無關setTimeout如何接收功能作爲它的參數,但它確實

+1

非常感謝。你的答案很好。不過,我仍然有一個困惑。你能告訴我爲什麼'mike.showName()'會先執行,而'function(){mike.showName()'等待5秒鐘?再次感謝。 – jsnewman 2011-04-02 01:15:21

+3

@jsnewman - 傳遞'mike.showName()'說現在運行'showName'函數並傳遞它返回的任何內容作爲要在5秒內執行的回調函數(沒什麼)。然而,傳遞'function(){mike.showName()}'提供了'setTimeout'和一個匿名函數,從現在起運行五秒鐘。五秒鐘過去並執行外部包裝函數。它包含一行,這是對'showName'的調用,該行在當時被執行。 – 2011-04-02 08:28:56

8

這不是性能問題。你顯示的一種方法不起作用(它立即調用該函數,而不是在超時觸發時)。

setTimeout(mike.showName(), 5000);將執行showName函數並將其返回值設置爲不起作用的超時回調。

setTimeout(function(){ mike.showName(); }, 5000);創建一個匿名函數並將其設置爲超時回調。當超時激活時,函數被調用並調用您的showName()函數。

Fyi,setTimeout('mike.showName();', 5000);也可以工作。但不這樣做 - 這和使用eval()一樣糟糕。除此之外,由於字符串中的代碼不能被語法高亮顯示,因此它會使代碼變得不可讀。

+0

'setTimeout(mike.ShowName,5000)'也可以工作 – 2011-04-02 00:20:27

+0

你能告訴我爲什麼'mike.showName()'會先執行,而'function(){mike.showName()'等待它的時間嗎?非常感謝。 – jsnewman 2011-04-02 00:28:33

+0

因爲你實際上調用該行中的函數。如果你把它封裝在一個匿名函數中,或者只是在沒有調用'()'的情況下傳遞函數,那麼函數本身就會被傳遞。 – ThiefMaster 2011-04-02 07:48:41

4

setTimeout(mike.showName(), 5000);立即執行mike.showName()並將返回值來setTimeout()

setTimeout(function(){ mike.showName(); }, 5000);將指針傳遞給函數來代替。那樣setTimeout可以執行該函數,而不是它的返回值。

12

如果接受的答案是太長時間閱讀:

setTimeout(mike.showName(), 5000); 

這將執行什麼mike.showName()回報後5000毫秒。

setTimeout(function(){ mike.showName(); }, 5000); 

這將後5000毫秒調用mike.showName()實際功能執行匿名函數。

另一種方式來實現同樣的效果:

setTimeout(mike.showName.bind(mike), 5000); 
+0

完全一致,接受答案不會幫助初學者。 – Pavel 2016-09-08 21:38:20

+0

我一直在尋找的最佳答案! – 2017-03-23 09:11:53

相關問題