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(表达式,1)">时间间隔)则不一样,它从载入后,1)">每隔指定的时间就执行一次表达式,只要窗口不关闭或 clearInterval() 调用就会无限循环下去。所以,两者是完全是不一样的,具体看下面测试代码和结果!

var intervalNum = 0,timeoutNum =0;
function testsetInterval(){
    var date = new Date();
    console.log(date.getSeconds());
    console.log("setInterval",intervalNum++);
}
 testsetTimeout(){
     Date();
    console.log(date.getSeconds());
    console.log("setTimeout",timeoutNum++ testFuntion() {
    setInterval( () {
        testsetInterval()
    },4000);  //每4秒执行testsetInterval()一次
    setTimeout(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 testsetInterval() {
     recursive() {
    testsetInterval();
    setTimeout(recursive()      递归,每隔4秒调用一次recursive()
    },4000)
}
 testFuntion() {
    recursive();        在方法recursive外,调用一次recursive,以启动循环调用!
}

  

循环执行,和setInterval()功能相同

  模拟 setTimeout() :用 setInterval() 模拟 setTimeout() 很简单,在 setInterval() 执行一次后,立刻关闭窗口(当然这是耍无赖)或者执行 clearInterval() 方法(这个靠谱点)。clearInterval() 需要在 setInterval()执行code方法内或其他地方执行,不能紧接着 setInterval() 后面执行,那样setInterval() 还没等到执行,就已经被干掉了。

 testsetInterval(){
    );
    clearInterval(clearId);     也可以在此执行
}
 testFuntion() {
    clearId = setInterval( () {
        testsetInterval();          每隔4秒调用testsetInterval()
         clearInterval(clearId);     //可以在此执行
    },1)">);
}

  

执行一次,关闭 setInterval(),和 setTimeout() 功能相同

  

  最后,将书中看到的“避免双重求值”搬到这。以解释为什么 “ 建议传入函数而不是字符串以作为第一个参数”。  

   setTimeout()、setInterval() 允许传入一个JS代码字符串并执行,然而在JS代码中执行另一段JS代码时,代码首先会以正常的方式求值,然后在执行过程中对包含于字符串中的代码发起另一个求值运算,从而造成双重求值。它比直接包含的代码执行速度慢很多,原因在于, 每次调用setTimeout()、setInterval()都会创建一个新的解释器/编译器实例。这必然使得代码执行速度变慢,效率降低,从而造成性能的浪费。所以建议传入函数而不是字符串来作为第一个参数。  

  我做了一个小测试。从 0 自加到 1亿,比较两种方式各自的实际耗时,代码以及测试结果如下:

var Timer ={     从书上copy的一个JS代码时间分析对象
    _data : {},start: (key) {
        Timer._data[key] =  Date();
    },stop: (key) {
        var time = Timer._data[key];
        if(time){
            Timer._data[key] = new Date()-time;
        }
    },getTime: return Timer._data[key];
        console.log("time = "+ Timer._data[key]);
    }
};

var intervalNum = 100000000,clearId = 100000000function 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亿,以 字符串方式 执行
    while(clearId-- clearId;
        } {
            temp = (clearId+1) + clearId;
        }
    }
    console.log(temp);
    Timer.stop("setTimeout");        testFuntion() {
    Timer.start("testsetInterval");     获取代码执行前的初始时间
    setTimeout( () {
        testsetInterval();      每隔1秒调用testsetInterval()
    },1000);

    Timer.start("setTimeout");
    setTimeout("testsetTimeout()",1000);    双重求值模式,每隔1秒调用testsetTimeout()
}

,随着数据量的攀升,耗时的差距,更明显。下面以 0 自加到 10亿,再试下

  看得出,“双重求值”对性能影响还是蛮大的。虽然现在的CPU主频都相当高,处理数据相当快,而平时前端处理数据的数量级,也不见得能达到这么高,但是养成一种好的编程习惯和塑造提高代码性能的思想总没得错!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)