变量中的代码在没有被调用的情况下触发?

时间:2016-04-02 16:38:02

标签: javascript

我在网上找到以下代码,在我的网站上插入一个时钟。在startTime()函数的最后一行中声明了一个变量t。然而,t中的代码似乎在没有被调用的情况下触发(这很明显,因为时钟在站点中完美运行)。

为什么这段代码有效?

我知道将函数指定为变量,这些函数在赋值时不会触发但需要调用。我也尝试了以下代码,而没有将setTimeout分配给t,它也有效。将它分配给变量有什么意义?

我是javascript的新手,所以任何可以帮助我理解这里发生的事情的解释都会很棒。

提前致谢!

代码:

function startTime() {
    var today = new Date();
    var h = today.getHours();
    var m = today.getMinutes();
    var s = today.getSeconds();
    m = checkTime(m);
    s = checkTime(s);
    document.getElementById('timeLink').innerHTML = "Time: " +
    h + ":" + m + ":" + s;
    var t = setTimeout(startTime, 500);
}
function checkTime(i) {
    if (i < 10) {i = "0" + i};  // add zero in front of numbers < 10
    return i;

3 个答案:

答案 0 :(得分:2)

这一行:

 var t = setTimeout(startTime, 500);

表示在500毫秒延迟后,应调用startTime函数。由于此代码在startTime内,因此该函数变为递归。 t变量将接收一个代表计时器特定实例的数字。如果您希望使用clearTimeout()功能取消计时器,可以在以后使用...您可以将它的引用传递给您要取消的计时器,如下所示:

clearTimeout(t);

看看这个小提琴,看看setTimeout()返回的实际值:https://jsfiddle.net/34s2g1f4/6/

顺便说一下,更简化的时钟代码是:

window.addEventListener("DOMContentLoaded", function(){

   var timeLink = document.getElementById('timeLink');
   var t = null;

   // The parenthesis around this function make it a function
   // expression and the extra set of parenthesis at the end
   // cause the function to invoke itself. This syntax is also
   // known as an "Immediately Invoked Function Expression"
   (function startTime() {
      timeLink.innerHTML = "Time: " + new Date().toLocaleTimeString();
      t = setTimeout(startTime, 900);
   }());

});

此代码每900毫秒更新一次,而不是每500毫秒更新一次(因此它自称近一半的时间,但仍保持时间准确)。

setTimeout()函数创建“一次性”计时器。定时器关闭后,调用提供的函数引用,这是它的结束,但在你的情况下,提供的函数引用是包含setTimeout()的函数,所以在第一次定时器关闭后,它调用再次使用当前功能,导致设置另一个“一次性”计时器,依此类推。当函数调用自身时,它被称为“递归函数”。

获得此行为的另一种方法是使用setInterval(),它会创建一个重复计时器,以您提供的间隔重复调用其功能。它看起来像这样:

window.addEventListener("DOMContentLoaded", function(){
   var timeLink = document.getElementById('timeLink');

   // Here, the call to start the timer is outside of the function
   // so startTime will not be recursive, it will just be called
   // repeatedly every 9/10's of a second.
   var t = setInterval(startTime, 900);
});

function startTime() {
   timeLink.innerHTML = "Time: " + new Date().toLocaleTimeString();
}

尽管接受的答案表明(这大多是错误的),setTimeout()setInterval()已经标准化并且已经有一段时间了。来自:https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

enter image description here

答案 1 :(得分:0)

分配变量时,会评估右侧,并将评估结果放入变量中。

所以如果你写:

var a = 5 + 6;

然后解释器将评估5 + 6,得到11的结果,并将a分配给数字11

功能也是如此。如果你写:

function someFunction() {
    return 9;
}
var x = someFunction();

解释器将评估someFunction,调用函数,得到9的结果,并将变量赋值为9。

这也适用于您的示例。

var t = setTimeout(startTime, 500);

口译员将:

  1. 评估右侧setTimeout(startTime, 500),然后
  2. 调用该函数(等待500ms,然后调用startTime)
  3. 获取结果,即计时器的ID
  4. 将该ID分配给t。
  5. 但是,您实际上并不需要变量t,因为它始终具有值null并且从未使用过它。在你的功能结束时,你可以写setTimeout(startTime, 500);,它会做同样的事情。

    <强>摘要

    函数实际上在赋值时触发,因此可以对它们进行求值以返回赋给变量的值。

    希望清理它!

答案 2 :(得分:0)

调用setTimeout()并将返回值赋给var t。此实例中的返回值是此setTimeout实例唯一的ID。