HTML5学堂-码匠 HTML5学堂

您当前位于:高级JS、面向对象 ——> 原生JavaScript setInterval与setTimeout参数详解

原生JavaScript setInterval与setTimeout参数详解

2015/05/05 11:24:40 | 作者:HTML5学堂(码匠) | 分类:高级JS、面向对象 | 关键词:setInterval,setTimeout

setInterval和setTimeout参数剖析

HTML5学堂:在平时使用的时候很少去注意计时器的参数问题,因为比较常用的是函数和时间这两个参数,很少遇到传入的是字符串类型的参数。本文给大家讲解的是当计时器传入的参数是字符串类型的时候,会出现什么问题?

当定时器第一个参数是函数名

  1. // 存储定时器返回的ID
  2. var timer = null;
  3.  
  4. function show() {
  5.  console.log("梦幻雪冰、独行冰海");
  6. }
  7.  
  8. timer = setInterval(show, 1000);
  9. console.log(timer);
  10.  
  11. // 当 setInterval 被调用时,它会返回一个 ID 标识并且计划在将来大约 1000 ms后调用 show函数。 show函数间隔1000ms多次执行。

注意:基于 JavaScript 引擎的计时策略,以及本质上的单线程运行方式,所以其它代码的运行可能会阻塞此线程。因此没法确保函数会在 setInterval 指定的时刻被调用(拿上面的那个例子来说,不能保证间隔1000ms调用一次)。

函数名与函数调用的区别

setInterval 的第一个参数是函数对象(函数的地址),一个常犯的错误是这样的 setInterval (show(), 1000),这里回调函数是 show 的返回值,而不是show本身。大部分情况下,这是一个潜在的错误。如果函数返回 undefined,setInterval 也不会报错。

当定时器第一个参数是匿名函数

  1. // 存储定时器返回的ID
  2. var timer = null;
  3.  
  4. timer = setInterval(function() {
  5.     console.log("梦幻雪冰、独行冰海");
  6. }, 1000);
  7. console.log(timer);

当定时器第一个参数是JavaScript代码串

setTimeout 和 setInterval 都可以接受字符串作为它们的第一个参数,但是这个特性绝对不要使用,因为它在内部使用了 eval(绝对不要使用 eval,任何使用它的代码都会在它的工作方式,性能和安全性方面受到质疑)。

  1. function show() {
  2.     // 将会被调用
  3.     console.log("梦幻雪冰");
  4. }
  5.  
  6. function test() {
  7.     function show() {
  8.         // 不会被调用
  9.         console.log("独行冰海");
  10.     }
  11.     setTimeout('show()', 2000);
  12. }
  13. test();

结果:输出的是 梦幻雪冰

解析:由于 eval 在这种情况下不是被直接调用(因为eval的作用域是当前执行的作用域,setTimeout的作用域是在全局,所以eval不是在函数test里面执行,而是在全局中执行),因此传递到 setTimeout 的字符串会自动在全局作用域中执行;因此,上面的回调函数使用的不是定义在 test 作用域中的局部变量 show。简单的理解,只能调用全局中声明的函数。

欢迎沟通交流~HTML5学堂

回调函数传递参数使用字符串形式

  1. function test(a, b) {
  2.     console.log(a + "和" + b);
  3. }
  4.  
  5. // 不推荐大家这样做,因为这样定时器就会使用到eval
  6. setTimeout('test(1, 2)', 2000);

使用匿名函数完成相同功能

  1. function test(a, b) {
  2.     console.log(a + "和" + b);
  3. }
  4.  
  5. // 可以使用匿名函数完成相同功能
  6. setTimeout(function() {
  7.   test(1, 88);
  8. }, 2000);

还有另外一种解决办法,但是在IE9以及IE9以下不支持。

  1. function test(a, b) {
  2.     console.log(a + "和" + b);
  3. }
  4.  
  5. setTimeout(test, 2000, 1, 2);

资料:

HTML5学堂 setInterval和setTimeout参数剖析 h5course

定时器第一个参数会在全局作用域中执行,因此函数内的 'this'将会指向这个全局对象

  1. function test(a, b) {
  2.     // this执行的是window
  3.     console.log(this);
  4. }
  5.  
  6. setTimeout(test, 2000);

总结:

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

欢迎沟通交流~HTML5学堂

微信公众号,HTML5学堂,码匠,原创文章,WEB前端,技术分享

HTML5学堂

原创前端技术分享

HTML5学堂,HTML5,WEB,前端,视频课程,技术视频,学习视频,面试,JS

原创视频课程

用心打造精品课程

微信小程序,决胜前端,面试题,面试题集合,前端,HTML5,真题

小程序-决胜前端

前端面试题宝库

原创书籍,学习书籍,书籍推荐,HTML5布局之路,HTML5,WEB前端

HTML5布局之路

非传统模式讲解前端

iOS,APP,码集,案例交互,JavaScript学习,WEB前端,HTML5

iOS APP 码集

案例交互式学习JS