2014-05-02 161 views
0

我對這個語法之間的區別感到困惑:遞歸調用setTimeout函數並傳遞一個匿名函數

var timerId; 
function clockStart(){ 
    // debugger; 
    if(timerId){ 
     return; 
    } 
    update(); 
    // THIS LINE BELOW ********************************************* 
    var timerId = setTimeout(function(){clockStart()}, 1000); 
    } 
    function clockStop(){ 
     timerId = null; 
    } 
    function update(){ 
     var date = new Date(); 
     var hours = date.getHours(); 
     var minutes = date.getMinutes(); 
     var seconds = date.getSeconds(); 
     if(hours < 10) { 
     hours = '0'+hours; 
     } 
     document.getElementById('hour').innerHTML = hours; 
     if(minutes < 10){ 
     minutes = 0+minutes; 
     } 
     document.getElementById('min').innerHTML = minutes; 
     if(seconds < 10){ 
      seconds = '0' + seconds; 
     } 
     document.getElementById('sec').innerHTML = seconds; 
    } 

我公司提供的被稱爲兩種功能,但這個功能我不明白的主要部分就是爲什麼我需要傳遞一個匿名函數來調用我的clockStart()函數。

我的功能工作時,我使用這個語法:

var timerId = setTimeout(function(){clockStart()}, 1000); 

但是,當我用不工作:

var timerId = setTimeout(clockStart(), 1000); 

我已經在這兩個功能,我工作了一段時間老老實實偶然偶然發現了這一點。除了調用clockStart函數之外,我真的沒有看到匿名函數在做什麼。但在我看來,我的clockStart()函數應該每秒調用一次(1000毫秒),因爲它調用自己,所以爲什麼它需要一個匿名函數來調用它?它不應該援引自己嗎?

如果你想看到這個數字時鐘的完整代碼,請檢查我的codepen link

+0

@ jfriend00對不起,我會刪除我的評論。 –

回答

4

這條線:

var timerId = setTimeout(clockStart(), 1000); 

立即調用clockStart(),並從該函數傳遞返回結果setTimeout()。由於該功能不會返回任何內容,因此您可以這樣做:

clockStart(); 
var timerId = setTimeout(undefined, 1000); 

這顯然不符合您的要求。


您可以使用它代替:

var timerId = setTimeout(clockStart, 1000); 

在這種情況下,你想傳遞一個函數引用setTimeout()這意味着你不包括括號。當你包含這些parens時,這意味着現在就執行它。當你傳遞函數的名字時,這只是對函數的引用(想象它像句柄),setTimeout()可以在稍後調用它。那就是你想要的。

當你這樣做:

var timerId = setTimeout(function(){clockStart()}, 1000) 

你只是定義一個匿名函數並傳遞一個引用匿名函數來setTimeout()的正常工作,但沒有必要在這種情況下,因爲你可以通過clockStart名稱,如上面我的第三個代碼示例。


既然您問到函數如何調用某個東西,我會告訴您一個簡單的例子。這是一個函數,它需要一個起始值,一個結束值,一個增量和一個回調函數。這將調用回調函數,並將它傳遞的值遞增,直到值超過最終值。

// define an increment function that will call a callback 
// multiple times based on the start, end and increment arguments 
function eachIncrement(start, end, increment, callback) { 
    // the function argument named callback contains 
    // a function reference 
    var val = start; 
    while (val <= end) { 
     // execute the function reference and 
     // pass it the current val 
     callback(val); 
     val += increment; 
    } 
} 

// define a function that we want to be called later 
function processValues(num) { 
    // this will get called multiple times with 
    // values 1, 4, 7, 10 
} 

// set up the increment parameters and pass a function reference 
eachIncrement(1, 10, 3, processValues); 
+0

它也可以在字符串模式下工作:'var timerId = setTimeout(「clockStart()」,1000);'https://developer.mozilla.org/en/docs/Web/API/window.setTimeout#Passing_string_literals –

+0

This是一個很好的答案。對此,我真的非常感激。我主要了解它們之間的區別,我唯一感到困惑的部分是'你想傳遞給setTimeout()的引用。所以我認爲這意味着不是調用並基本插入返回值(您在上面解釋過),而是傳遞一個對函數對象的引用,以後將調用它?什麼讓它'以後調用它'?我對遞歸沒有太大的把握,如果它與遞歸有關,我當然可以查看它。我只是不太明白clockStart是如何用()調用的? – HelloWorld

+1

@HelloWorld - 它與遞歸無關。函數名稱只是一個函數引用。您僅通過名稱將其作爲參考傳遞。你通過在末尾加上'()'來執行它。查看我添加到答案末尾的示例。 – jfriend00