资讯专栏INFORMATION COLUMN

细说 Javascript 拾遗篇(四) : setTimeout 和 setInterval

wangjuntytl / 3410人阅读

摘要:当间隔时间设置较小时,将会导致回调函数堆积。处理可能阻塞的代码最简单且最可控的方式就是在回调函数内部使用函数。但是很明显,由于指定最大值的限制,还会有定时器没有被清除掉。另外,尽量避免使用函数,从而避免可能导致的回调函数堆积现象。

由于 Javascript 是异步的,因此我们可以通过 setTimeoutsetInterval 函数来指定特定时间执行代码。

function foo() {}
var id = setTimeout(foo, 1000); // returns a Number > 0

上例中,当 setTimeout 函数被调用时,它会返回一个标志延时的 ID 并计划在大约 1000 毫秒后调用 foo 函数,函数 foo 将只会执行一次。
根据 Javascript 引擎的计时方法,以及 Javascript 单线程的本质,因此其他代码执行时可能会阻塞此线程,我们无法保证 setTimeout 函数内调用的函数会在指定的时间被执行。
setTimeout 函数的第一个参数将会在全局作用域内执行,因此参数内的 this 将会指向全局对象。

function Foo() {
    this.value = 42;
    this.method = function() {
        // this refers to the global object
        console.log(this.value); // will log undefined
    };
    setTimeout(this.method, 500);
}
new Foo();

这里要注意一个常犯的错误,setTimeout 函数的第一个参数指的是函数对象本身,不能写成类似 setTimeout(foo(), 1000),因为 foo() 是函数返回值,而不是 foo 本身。

setInterval 函数的堆调用

从上文已知,setTimeout 中的回调函数只会执行一次,而 setInterval 函数,正如函数的名字一样,它会每隔指定时间执行一次回调函数。
即使回调函数的执行被阻塞,setInterval 函数依然会继续调用更多的回调函数。当间隔时间设置较小时,将会导致回调函数堆积。

function foo(){
    // something that blocks for 1 second
}
setInterval(foo, 1000);

上述代码中,函数 foo 被调用后将被阻塞一秒钟。

处理可能阻塞的代码

最简单且最可控的方式就是在回调函数内部使用 setTimeout 函数。

function foo(){
    // something that blocks for 1 second
    setTimeout(foo, 1000);
}
foo();

这样不仅封装了 setTimeout 的调用,同时也阻止了可能存在的回调函数堆积。foo 函数现在可以自己控制是否继续或终止。

手动清除定时器

清除定时器可以通过传递指定的 IDclearTimeoutclearInterval 函数。

var id = setTimeout(foo, 1000);
clearTimeout(id);
清除所有的定时器

Javascript 中并没有内置的函数方法来清除所有的定时器(timeoutinterval),不过我们可以使用一种暴力的方法来清除所有的定时器。

// clear "all" timeouts
for(var i = 1; i < 1000; i++) {
    clearTimeout(i);
}

但是很明显,由于指定最大值的限制,还会有定时器没有被清除掉。由于 ID 会随着定时器被调用的增加而增加,因此更好的方法是记录下最大的 ID 并一起清除。

// clear "all" timeouts
var biggestTimeoutId = window.setTimeout(function(){}, 1),
i;
for(i = 1; i <= biggestTimeoutId; i++) {
    clearTimeout(i);
}
eval 的隐式使用

setTimeoutsetInterval 函数的第一个参数也可以接收字符串,但是尽量不要使用这个功能,因为这会在内部调用 eval 函数来执行这段字符串。

function foo() {
    // will get called
}

function bar() {
    function foo() {
        // never gets called
    }
    setTimeout("foo()", 1000);
}
bar();

由于 eval 函数并没有在上例中被直接调用,因此传递到 setTimeout 函数的字符串将会在全局作用域下被执行,所以不会调用函数 bar 内部的 foo 函数。
建议尽量不要在使用定时器函数时通过字符串形式来传递参数。

function foo(a, b, c) {}

// NEVER use this
setTimeout("foo(1, 2, 3)", 1000)

// Instead use an anonymous function
setTimeout(function() {
    foo(a, b, c);
}, 1000)
总结

不要使用字符串作为 setTimeoutsetInterval 函数的参数,当需要向回调函数中传递参数时,我们可以用匿名函数的,在匿名函数内部执行回调函数。
另外,尽量避免使用 setInterval 函数,从而避免可能导致的回调函数堆积现象。

参考

http://bonsaiden.github.io/JavaScript-Garden/#other.timeouts

后言

终于将整个 Javascript Garden 都学习了一遍,基本上每一个章节都翻译了一遍,同时加上了自己的一些想法和笔记,大概花了半个多月的时间,感觉这的的确确是个很适合自己的学习方法,有时候忘记某些概念,我立马就能在自己的博客中找到相关的知识并及时回顾,由于出自自己的笔下,所以很快就能回忆起来。希望自己能坚持这个好的习惯,也希望自己的博文能给博友们带来些许的帮助,大家相互学习,共同进步!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78124.html

相关文章

  • 细说 Javascript 遗篇(一) : 远离 eval 函数

    摘要:然而,函数只有在当前作用域中直接被调用并且被调用的函数名为才会被执行。在全局作用域下,这个字符串会一直被执行,在这个情形下我们并没有直接调用函数,也可以执行字符串。总结函数应该尽可能地避免使用。 Javascript 的 eval 函数可以在当前作用域执行一段包含 Javascript 代码的字符串。 var foo = 1; function test() { var fo...

    imtianx 评论0 收藏0
  • 细说 Javascript 遗篇(二) : undefined null

    摘要:有两个可以表示空的值,分别是和,比较有作用的是前者。访问声明但未初始化的变量。有返回值时函数的表达式没有显式的返回任何内容。然而,为了比较其他变量和值,我们需要提前取得的值。因此,从标准实行后,全局变量已经是不再可写。 Javascript 有两个可以表示空的值,分别是 undefined 和 null,比较有作用的是前者。 undefined undefined 是一种值为 un...

    My_Oh_My 评论0 收藏0
  • 细说 Javascript 遗篇(三) : 自动插入分号

    摘要:此时会自动插入分号,解析器将再次尝试。工作原理下面的代码没有分号,因此解析器将会自己判断在哪些地方插入分号。前置小括号在有前置小括号的情形时,解析器将不会自动插入分号。这不仅将保证代码整体的一致性,也将有效地避免解析器对代码行为的错误改变。 尽管 Javascript 有类似 C 的句法风格,但是它并不强制在代码中使用分号,所以分号可能被省略。Javascript 并不是一个缺少分号的...

    mushang 评论0 收藏0
  • 简单说 JavaScript实现雪花飘落效果

    摘要:说明这次实现的雪花飘落的效果很简单,主要是为了练习练习中的定时器,和。简单说,意思就是用了这个定时器,能把两次修改样式的代码分开执行,可以先把第一次修改的样式渲染后,在进行第二次的修改,雪花就会动了。 说明 这次实现的雪花飘落的效果很简单,主要是为了练习练习JavaScript中的定时器,setTimeout 和 setInterval。 效果图 showImg(https://seg...

    yedf 评论0 收藏0
  • 简单说 JavaScript实现雪花飘落效果

    摘要:说明这次实现的雪花飘落的效果很简单,主要是为了练习练习中的定时器,和。简单说,意思就是用了这个定时器,能把两次修改样式的代码分开执行,可以先把第一次修改的样式渲染后,在进行第二次的修改,雪花就会动了。 说明 这次实现的雪花飘落的效果很简单,主要是为了练习练习JavaScript中的定时器,setTimeout 和 setInterval。 效果图 showImg(https://seg...

    ShowerSun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<