settimeout、setinterval区别和相互模拟
前几天翻书,看到“避免双重求值”一节时有提到settimeout()、setinterval() 建议传入函数而不是字符串以作为第一个参数,所以这里总结一下settimeout()和setinterval()的区别,以及它们之间的相互模拟。
setTimeout(): 方法用于在指定的毫秒数后调用函数或计算表达式(函数更好,下面会解释为什么函数更好!)。
语法:setTimeout(code,millisec) code:必需,要调用的函数后要执行的 JavaScript 代码串;millisec:必需,在执行代码前需等待的毫秒数。
setInterval() :方法用于按照指定的周期(以毫秒计)来循环调用函数或计算表达式,直到 clearInterval() 被调用或窗口关闭,由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
语法:setInterval(code,millisec[,"lang"]) code:必需,要调用的函数或要执行的JavaScript 代码串;millisec:必须,周期性执行或调用 code 之间的时间间隔,以毫秒计。
从上面的定义可以看出,setTimeout(表达式,延时时间)在执行时,是在载入后延迟指定时间后,去执行一次表达式,次数是一次;而 setInterval(表达式,时间间隔)则不一样,它从载入后,每隔指定的时间就执行一次表达式,只要窗口不关闭或 clearInterval() 调用就会无限循环下去。所以,两者是完全是不一样的,具体看下面测试代码和结果!
var intervalNum = 0, timeoutNum =0;
function testsetInterval(){
var date = new Date();
console.log(date.getSeconds());
console.log("setInterval", intervalNum++);
}
function testsetTimeout(){
var date = new Date();
console.log(date.getSeconds());
console.log("setTimeout", timeoutNum++);
}
function testFuntion() {
setInterval(function () {
testsetInterval()
},4000); //每4秒执行testsetInterval()一次
setTimeout(function () {
testsetTimeout()
},10000); //延迟10秒执行testsetTimeout()一次,只执行一次;单独的setTimeout()方法,需要有另外的方法去触发,如将其放在 body 的 onload事件方法内
}

从图中的结果可以看出,setInterval() 每4秒循环执行一次;然而setTimeout()在延迟10秒(37+10),执行一次后,再没执行!
虽然两者不一样,但是却可以相互模拟。具体使用那个,以具体的需求和场景具体分析,就像for循环可以模拟所有的循环一样(包括分支,以及do while一样)。一般情况下 setTimeout() 用于延迟执行某方法或功能;setInterval() 则一般用于刷新表单,对于一些表单的假实时指定时间刷新同步。
模拟 setInterval() :将 setTimeout() 包含在一个执行函数A中,而setTimeout() 自己的code执行函数又是A,然后在函数A外将函数A执行一次,即达到了循环执行的目的。
var intervalNum = 0;
function testsetInterval() {
var date = new Date();
console.log(date.getSeconds());
console.log("setInterval", intervalNum++);
}
function recursive() {
testsetInterval();
setTimeout(function () {
recursive() //递归,每隔4秒调用一次recursive()
}, 4000)
}
function testFuntion() {
recursive(); //在方法recursive外,调用一次recursive,以启动循环调用!
}
循环执行,和setInterval()功能相同
模拟 setTimeout() :用 setInterval() 模拟 setTimeout() 很简单,在 setInterval() 执行一次后,立刻关闭窗口(当然这是耍无赖)或者执行 clearInterval() 方法(这个靠谱点)。clearInterval() 需要在 setInterval()执行code方法内或其他地方执行,不能紧接着 setInterval() 后面执行,那样setInterval() 还没等到执行,就已经被干掉了。
var intervalNum = 0, clearId = 0;
function testsetInterval(){
var date = new Date();
console.log(date.getSeconds());
console.log("setInterval", intervalNum++);
clearInterval(clearId); //也可以在此执行
}
function testFuntion() {
clearId = setInterval(function () {
testsetInterval(); //每隔4秒调用testsetInterval()
// clearInterval(clearId); //可以在此执行
},4000);
}
执行一次,关闭 setInterval(),和 setTimeout() 功能相同
最后,将书中看到的“避免双重求值”搬到这。以解释为什么 “ 建议传入函数而不是字符串以作为第一个参数”。
setTimeout()、setInterval() 允许传入一个JS代码字符串并执行,然而在JS代码中执行另一段JS代码时,代码首先会以正常的方式求值,然后在执行过程中对包含于字符串中的代码发起另一个求值运算,从而造成双重求值。它比直接包含的代码执行速度慢很多,原因在于, 每次调用setTimeout()、setInterval()都会创建一个新的解释器/编译器实例。这必然使得代码执行速度变慢,效率降低,从而造成性能的浪费。所以建议传入函数而不是字符串来作为第一个参数。
我做了一个小测试。从 0 自加到 1亿,比较两种方式各自的实际耗时,代码以及测试结果如下:
var Timer ={ //从书上copy的一个JS代码时间分析对象
_data : {},
start:function (key) {
Timer._data[key] = new Date();
},
stop:function (key) {
var time = Timer._data[key];
if(time){
Timer._data[key] = new Date()-time;
}
},
getTime:function (key) {
// return Timer._data[key];
console.log("time = "+ Timer._data[key]);
}
};
var intervalNum = 100000000, clearId = 100000000;
function testsetInterval(){ //计算从0 加到 1亿,以 传入函数方式 执行
var temp = 0;
while(intervalNum--){
if(temp !== 0){
temp = temp + intervalNum;
}else {
temp = (intervalNum+1) + intervalNum;
}
}
console.log(temp);
Timer.stop("testsetInterval"); //调用stop(),计算时间差
Timer.getTime("testsetInterval"); //将时间差值打印出来
}
function testsetTimeout(){ //计算从0 加到 1亿,以 字符串方式 执行
var temp = 0;
while(clearId--){
if(temp !== 0){
temp = temp + clearId;
}else {
temp = (clearId+1) + clearId;
}
}
console.log(temp);
Timer.stop("setTimeout"); //调用stop(),计算时间差
Timer.getTime("setTimeout"); //将时间差值打印出来
}
function testFuntion() {
Timer.start("testsetInterval"); //获取代码执行前的初始时间
setTimeout(function () {
testsetInterval(); //每隔1秒调用testsetInterval()
},1000);
Timer.start("setTimeout");
setTimeout("testsetTimeout()",1000); //双重求值模式,每隔1秒调用testsetTimeout()
}
,随着数据量的攀升,耗时的差距,更明显。下面以 0 自加到 10亿,再试下
看得出,“双重求值”对性能影响还是蛮大的。虽然现在的CPU主频都相当高,处理数据相当快,而平时前端处理数据的数量级,也不见得能达到这么高,但是养成一种好的编程习惯和塑造提高代码性能的思想总没得错!
settimeout、setinterval区别和相互模拟的更多相关文章
- setTimeout setInterval 区别 javascript线程解释
原文:http://www.iamued.com/qianduan/1645.html 今天看到这篇文章,学到了不少东西 特此发出来 和大家分享 JavaScript的setTimeout与setIn ...
- setInterval与setTimeout的区别
在制作网页动态效果时,一定会遇到某些需求,要求某段程序等待多时时间后再开始执行,就像在我们的生活中一样,待会儿再开始做一件事.在JavaScript中主要通过定时器实现此类需求,本文将对定时器做一个概 ...
- js setTimeout和setInterval区别
1.区别 2.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&qu ...
- 第46天:setInterval与setTimeout的区别
js的setTimeout方法用处比较多,通常用在页面刷新了.延迟执行了等等.今天对js的setTimeout方法做一个系统地总结. setInterval与setTimeout的区别 说道setTi ...
- val();html();.text()区别 setInterval与setTimeout的区别
val();html();.text()区别 对于innerHTML 属性,几乎所有的元素都有innerHTML属性,它是一个字符串,用来设置或获取位于对象起始和结束标签内的HTML.(获取HTM ...
- setTimeout与setInterval区别
setTimeout与setInterval区别 代码 setTimeout("showresponse('${rootUrl}index/movie.do','movieId')" ...
- js,onblur后下一个控件获取焦点判断、html当前活跃控件、jquery版本查看、jquery查看浏览器版本、setTimeout&setInterval
需求: input控件在失去焦点后直接做验证,验证通不过的话,显示相应错误.但是如果失去焦点后点击的下个控件是比较特殊的控件(比如,退出系统),那么不执行验证操作,直接退出系统(防止在系统退出前,还显 ...
- setTimeout,setInterval你不知道的…
javascript线程解释(setTimeout,setInterval你不知道的事) 标签: javascript引擎任务浏览器functionxmlhttprequest 2011-11-21 ...
- setTimeout,setInterval你不知道的事
javascript线程解释(setTimeout,setInterval你不知道的事) 标签: javascript引擎任务浏览器functionxmlhttprequest 2011-11-21 ...
随机推荐
- while 语句
/* while循环 格式:while(循环保持条件){需要执行的语句} OC: int i = 0; int sum = 0; while (i <= 10) { sum = i++; } w ...
- manifest.xml
main action 和 laucher的categoty If either the MAIN action or LAUNCHER category are not declared for o ...
- 6.关于Xamarin Android对APK包大小的处理
降低学习成本是每个.NET传教士义务与责任. 建立生态,保护生态,见者有份. 对于apk 包的大小大家都是很敏感的,虽然现在安卓手机的性能和存储越来越厉害了.本着能少一点是一点的态度,我们还是要深入理 ...
- artTemplate-优秀的前端模板引擎
artTemplate-优秀的前端模板引擎 1.html中引入artTemplate的js文件: <script type="text/javascript" src=&qu ...
- Maven-pom.xml文件报错 Plugin execution not covered by lifecycle configuration
问题: Eclipse中新导入的项目pom.xml文件报错: Plugin execution not covered by lifecycle configuration: org.jacoco:j ...
- CRF两个例子的理解
概率计算例子: 预测例子:
- Node.js最新Web技术栈(2016年4月)
Node.js是比较简单的,只有你有前端js基础,那就按照我的办法来吧!一周足矣,虽然这版上了es语法,但依然是可以简单写,也可以难写,参见<全栈工程师之路-Node.js>,里面讲了No ...
- java 使用 pdf.js 在线查看 pdf 文档
1. 下载对应的 pdf.js 文件: 推荐地址: https://github.com/mozilla/pdf.js/ http://mozilla.g ...
- Hive是什么
Hive是什么1)Hive 是建立在Hadoop (HDFS/MR)上的用于管理和查询结果化/非结构化的数据仓库:2)一种可以存储.查询和分析存储在Hadoop 中的大规模数据的机制:3)Hive 定 ...
- C/C++ 类型内存占用详解
最近做一些面试题目碰到了很多次考察C/C++类型内存占用的题目,主要考察队C/C++的指针.类型等的熟悉程度. 本blog为了方面大家参考,总结了常见的类型内存占用的情况,能力所限,若有问题,请指出! ...