前几天翻书,看到“避免双重求值”一节时有提到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区别和相互模拟的更多相关文章

  1. setTimeout setInterval 区别 javascript线程解释

    原文:http://www.iamued.com/qianduan/1645.html 今天看到这篇文章,学到了不少东西 特此发出来 和大家分享 JavaScript的setTimeout与setIn ...

  2. setInterval与setTimeout的区别

    在制作网页动态效果时,一定会遇到某些需求,要求某段程序等待多时时间后再开始执行,就像在我们的生活中一样,待会儿再开始做一件事.在JavaScript中主要通过定时器实现此类需求,本文将对定时器做一个概 ...

  3. js setTimeout和setInterval区别

    1.区别 2.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&qu ...

  4. 第46天:setInterval与setTimeout的区别

    js的setTimeout方法用处比较多,通常用在页面刷新了.延迟执行了等等.今天对js的setTimeout方法做一个系统地总结. setInterval与setTimeout的区别 说道setTi ...

  5. val();html();.text()区别 setInterval与setTimeout的区别

    val();html();.text()区别   对于innerHTML 属性,几乎所有的元素都有innerHTML属性,它是一个字符串,用来设置或获取位于对象起始和结束标签内的HTML.(获取HTM ...

  6. setTimeout与setInterval区别

    setTimeout与setInterval区别 代码 setTimeout("showresponse('${rootUrl}index/movie.do','movieId')" ...

  7. js,onblur后下一个控件获取焦点判断、html当前活跃控件、jquery版本查看、jquery查看浏览器版本、setTimeout&setInterval

    需求: input控件在失去焦点后直接做验证,验证通不过的话,显示相应错误.但是如果失去焦点后点击的下个控件是比较特殊的控件(比如,退出系统),那么不执行验证操作,直接退出系统(防止在系统退出前,还显 ...

  8. setTimeout,setInterval你不知道的…

    javascript线程解释(setTimeout,setInterval你不知道的事) 标签: javascript引擎任务浏览器functionxmlhttprequest 2011-11-21 ...

  9. setTimeout,setInterval你不知道的事

    javascript线程解释(setTimeout,setInterval你不知道的事) 标签: javascript引擎任务浏览器functionxmlhttprequest 2011-11-21 ...

随机推荐

  1. swift 3.0 正则表达式查找/替换字符

    1.什么是正则表达式 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符 ...

  2. 【PaddlePaddle系列】报错解决方法合集 (不定时更新)

    1.PaddlePaddle使用CPU时正常运行,但是使用GPU时却报出一堆错误信息,节选如下: paddle.fluid.core.EnforceNotMet: enforce allocating ...

  3. Winform—C#读写config配置文件

    现在FrameWork2.0以上使用的是:ConfigurationManager或WebConfigurationManager.并且AppSettings属性是只读的,并不支持修改属性值. 一.如 ...

  4. Java序列化接口Serializable接口的作用总结

    一.Java序列化接口Serializable的作用: 一个对象有对应的一些属性,把这个对象保存在硬盘上的过程叫做”持久化”. 对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字 ...

  5. django框架--路由系统

    目录 一.路由系统理解 二.路由系统功能划分 三.路由表创建 创建工具 二级路由 路由别名 动态路由及重定向 四.自定义错误页面 五.图示路由系统在框架中的定位 六.路由系统的进阶想法 一.路由系统理 ...

  6. (转)Db2数据库一次生产故障详细记录---数据库坏页

    原文:http://www.talkwithtrend.com/Article/216335 前言 数据库最严重的故障莫过于数据库损坏.数据库坏页是数据库损坏的一种,如果数据库中有数据页出现损坏,在没 ...

  7. sql server 2012 数据库日志文件过大,怎么缩小?

    最近发现网站不能访问,原因数据库服务器磁盘剩余空间没了.再细查发现日志文件占用了70%,收缩日志文件失败. 在网上查找原因,是没有备份不能收缩日志文件. 临时解决的方式: 备份事务日志,再收缩日志文件 ...

  8. Impala配置HA-Nginx

    Impala的高可用配置,官方的例子用的是Haproxy,考虑到nginx配置简单,使用人群广泛,再加上nginx1.9以后支持TCP的负载均衡,所以选用nginx. nginx安装:yum inst ...

  9. 开源微信支付SDK

    应该有一年多没在博客园上写文章了,毕竟是一个记录自己技术成长的平台,没能将写博客长期坚持下来,说起来也是挺惭愧的.对于自己的近况而言,确实平常加班也比较多,时间会比较压缩,所以到后来博客也基本停止了更 ...

  10. 我与GitHub的第一次——自制音乐文件修改器

    背景: 随机播放,所有的音乐播放器里面现在几乎都有这个功能吧.但是有没有发现,自己的播放器在选择随机播放的时候,经常会听到重复顺序的歌曲呢?反正我是有这样的感觉,无耐自己平时下的歌曲都是“歌手名—歌曲 ...