2014-05-02 40 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