setTimeout
和 setInterval
由于 JavaScript 是异步的,可以使用 setTimeout
和 setInterval
来计划执行函数。
注意: 定时处理不是 ECMAScript 的标准,它们在 DOM (文档对象模型) 被实现。
function foo() {}
var id = setTimeout(foo, 1000); // 返回一个大于零的数字
当 setTimeout
被调用时,它会返回一个 ID 标识并且计划在将来大约 1000 毫秒后调用 foo
函数。
foo
函数只会被执行一次。
基于 JavaScript 引擎的计时策略,以及本质上的单线程运行方式,所以其它代码的运行可能会阻塞此线程。
因此没法确保函数会在 setTimeout
指定的时刻被调用。
作为第一个参数的函数将会在全局作用域中执行,因此函数内的 this
将会指向这个全局对象。
function Foo() {
this.value = 42;
this.method = function() {
// this 指向全局对象
console.log(this.value); // 输出:undefined
};
setTimeout(this.method, 500);
}
new Foo();
注意: setTimeout
的第一个参数是函数对象,一个常犯的错误是这样的 setTimeout(foo(), 1000)
,
这里回调函数是 foo
的返回值,而不是foo
本身。
大部分情况下,这是一个潜在的错误,因为如果函数返回 undefined
,setTimeout
也不会报错。
setInterval
的堆调用
setTimeout
只会执行回调函数一次,不过 setInterval
- 正如名字建议的 - 会每隔 X
毫秒执行函数一次。
但是却不鼓励使用这个函数。
当回调函数的执行被阻塞时,setInterval
仍然会发布更多的毁掉指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。
function foo(){
// 阻塞执行 1 秒
}
setInterval(foo, 100);
上面代码中,foo
会执行一次随后被阻塞了一分钟。
在 foo
被阻塞的时候,setInterval
仍然在组织将来对回调函数的调用。
因此,当第一次 foo
函数调用结束时,已经有 10 次函数调用在等待执行。
处理可能的阻塞调用
最简单也是最容易控制的方案,是在回调函数内部使用 setTimeout
函数。
function foo(){
// 阻塞执行 1 秒
setTimeout(foo, 100);
}
foo();
这样不仅封装了 setTimeout
回调函数,而且阻止了调用指令的堆积,可以有更多的控制。
foo
函数现在可以控制是否继续执行还是终止执行。
手工清空定时器
可以通过将定时时产生的 ID 标识传递给 clearTimeout
或者 clearInterval
函数来清除定时,
至于使用哪个函数取决于调用的时候使用的是 setTimeout
还是 setInterval
。
var id = setTimeout(foo, 1000);
clearTimeout(id);
清除所有定时器
由于没有内置的清除所有定时器的方法,可以采用一种暴力的方式来达到这一目的。
// 清空"所有"的定时器
for(var i = 1; i < 1000; i++) {
clearTimeout(i);
}
可能还有些定时器不会在上面代码中被清除(译者注:如果定时器调用时返回的 ID 值大于 1000),
因此我们可以事先保存所有的定时器 ID,然后一把清除。
隐藏使用 eval
setTimeout
和 setInterval
也接受第一个参数为字符串的情况。
这个特性绝对不要使用,因为它在内部使用了 eval
。
注意: 由于定时器函数不是 ECMAScript 的标准,如何解析字符串参数在不同的 JavaScript 引擎实现中可能不同。
事实上,微软的 JScript 会使用 Function
构造函数来代替 eval
的使用。
function foo() {
// 将会被调用
}
function bar() {
function foo() {
// 不会被调用
}
setTimeout('foo()', 1000);
}
bar();
由于 eval
在这种情况下不是被直接调用,因此传递到 setTimeout
的字符串会自全局作用域中执行;
因此,上面的回调函数使用的不是定义在 bar
作用域中的局部变量 foo
。
建议不要在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。
function foo(a, b, c) {}
// 不要这样做
setTimeout('foo(1,2, 3)', 1000)
// 可以使用匿名函数完成相同功能
setTimeout(function() {
foo(a, b, c);
}, 1000)
注意: 虽然也可以使用这样的语法 setTimeout(foo, 1000, a, b, c)
,
但是不推荐这么做,因为在使用对象的属性方法时可能会出错。
(译者注:这里说的是属性方法内,this
的指向错误)
结论
绝对不要使用字符串作为 setTimeout
或者 setInterval
的第一个参数,
这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。
另外,应该避免使用 setInterval
,因为它的定时执行不会被 JavaScript 阻塞。
相关推荐
timercpp:为C 开发提供类似于Javascript中的setTimeout和setInterval功能
NULL 博文链接:https://rainbow702.iteye.com/blog/1668935
Javascript的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请求获取最新数据等等。但它们的应用是有区别的。 ...
JS中的setTimeout和setInterval的区别JS中的setTimeout和setInterval的区别JS中的setTimeout和setInterval的区别
使用SetInterval和设定延时函数setTimeout 很类似。setTimeout 运用在延迟一段时间,再进行某项操作。
JavaScript中setTimeout和setInterval函数的传参及调用_.docx
Javascript定时器(二)——setTimeout与setInterval 在 http://www.cnblogs.com/strick/p/3983904.html 有说明
js代码-settimeout 模拟实现 setinterval(带清除定时器的版本)
04-setTimeout.html
主要介绍了JavaScript中从setTimeout与setInterval到AJAX异步,非常不错,具有参考借鉴价值,需要的朋友可以参考下
window对象有两个主要的定时方法,分别是setTimeout 和 setInteval 他们的语法基本上相同,但是完成的功能取有区别。
给c#添加SetTimeout和SetInterval函数.docx
JS中定时执行,setTimeout和setInterval的区别 <br>setTimeout(Expression,DelayTime),在DelayTime过后,将执行一次Expression,setTimeout 运用在延迟一段时间,再进行某项操
unref()和ref()用法非常的简单,就是取消和回复setTimeout和...//取消setTimeout和setInterval函數的調用 timer.ref();//恢復setTimeout和setInterval函數的調用 是不是超级简单,如果还不明白,请放过javascript吧
必需,要调用的函数后要执行的 JavaScript 代码串。 millisec 必需,在执行代码前需等待的毫秒数。 setTimeinterval setInterval(code,millisec[,”lang”]) 参数 描述 code 必需,要调用的函数或要...
主要帮助大家学习理解javascript定时器中的setTimeout与setInterval,从实例出发进行深入探讨,感兴趣的小伙伴们可以参考一下
今天先学下setTimeout和setInterval的使用。 一、setTimeout超时计时器(和GCD中的after类似) 在node.js中可以使用node.js内置的setTimeout(callback,delayMillSeconds,[args])方法。当调用setTime()时回调函数会在...
在Javascript里,setTimeout和setInterval接收第一个参数是一个字符串或者一个函数,当在一个对象里面用setTimeout延时调用该对象的方法时 代码如下: function obj() { this.fn = function() { alert(...