1.setTimeout和setInterval都属于js中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直循环执行下去。

下面介绍一下两种定时器的语法:

setTimeout(expression,milliseconds)  以及 setInterval(expression,milliseconds)

其中 expression是将要执行的某一项操作,而milliseconds则是延迟时间,expression可以是一个将要执行的函数名,也可以是一个字符串

比如:

 function fun(){
alert('hello');
}
setTimeout(fun,1000); //参数是函数名
setTimeout('fun()',1000); //参数是字符串
setInterval(fun,1000);
setInterval('fun()',1000);

在上面代码中,无论是setTimeout还是setInterval,在使用函数名作为调用句柄时不能带参数,使用字符串调用时可以带参数,如:setTimeout('fun(name)',1000);

但是有些场合会要求必须使用函数名作为调用句柄,此时可以用另一种方法带参数:

方法一:

function fun(name){
alert('hello'+' ' +name);
}
function _fun(name){
return function(){
fun(name);
}
}
setTimeout(_fun('Tom'),1000); //参数是函数名

方法二:

不用单独再定义一个函数,直接将函数调用放在一个函数里面,可以使用函数名作为调用句柄:

function fun(name){
alert('hello'+' ' +name);
}
setTimeout(function(){
fun('Tom');
},1000); //参数是函数名

setInterval使用方式一样,就不再多写了。

在以上代码中,setTimeout和setInterval的区别就是 setTimeout延迟一秒弹出'hello',之后便不再运行;而setInterval则会每隔一秒钟弹出'hello',直至用clear来清除

清除定时器的语法:

定时器会返回一个id,只要对这个id进行清除的操作即可:

 function fun(){
alert('hello');
}
var t1 = setTimeout(fun,1000);
var t2 = setInterval(fun,1000);
clearTimeout(t1);
clearInterval(t2);

2. 用setTimeout实现setInterval的功能

虽然setTimeout只在延时时间后执行一次,但是我们可以使用递归调用的方法实现循环调用,实现类似setInterval的功能,例:

 function fun(){
alert('hello');
setTimeout(fun,1000);
}
fun();

以上代码的功能是每隔一秒钟页面便弹出“hello”,相当于setInterval的循环间隔调用。

但是即使可以实现同样的功能,两种定时器也还是有运行方面的差别:

比如延时1s执行函数fun(),但是函数内部的操作执行需要的时间是2S,由于JavaScript是单线程的,那在这次执行完之前,下一次的循环便被阻塞了,处在排队的状态,当此次操作执行完以后才会执行处在排队状态的操作,

但是排队的序列太多,阻塞结束以后只能执行一个,这样会造成性能的浪费,

所以在这样的情况下,使用setTimeout递归调用实现循环的方法便显得很方便,它不会发生阻塞的状况

比如函数内部的执行需要2S,那setTimeout会等2S执行完以后才去递归调用,也就是说整个一次循环需要3S的时间。

但是setTimeout又不如setInterval执行的精确,所以在不同情况下可以选择不同的定时器以达到最好的效果。

3.如何写出一个高效的倒计时

身为小白的我目前能写出来的只是能实现该需求的最低级的代码OTZ

 var t,num = 60;
function timeDown(){
num--;
num = num < 10 ? ('0'+num) : (num+''); // 左侧补0操作
document.getElementById('demo').innerHTML = num;
t = setTimeout(function(){
timeDown();
},1000);
if(num <= 0){
clearTimeout(t);
}
}
timeDown();

以上代码是用setTimeout递归调用外层函数实现的

下面是用setInterval实现的方法:

 var t,num = 5;
function timeDown(){
num--;
num = num < 10 ? ('0'+num) : (num+'');
document.getElementById('demo').innerHTML = num;
if(num <= 0){
window.clearInterval(t);
}
}
t = setInterval(timeDown,1000);

以上用两种定时器写出的代码都是运用的最基本的实现方式,也是我现在的经验和水平能写出来的,

前段时间在掘金社区看到一个很厉害的由浅入深的写倒计时的方法,现在粘贴过来跟我的对比一下,简直无地自容OTZ

首先是左侧补0的几种方法:

//方法一:大于10的返回值的类型是number类型,没有做转换
function leftPad(i){
if(i<10){
i = "0" + i;
}
return i;
}
//方法二:对上一种方法做了弥补,但是没有考虑到复数的情况
function leftPad(i){
return i < 10 ? '0'+i : i+'';
}
//方法三:对返回值类型做了转换,同时也考虑到了负数的情况,这也是目前我的水平能想到的写法了。。
function leftPad(n){
var n = parseInt(n, 10);
return n > 0 ? n <= 9 ? ('0'+n) : (n+'') :'00';
}
//下面两种方法我其实就有点看不懂了,不过还是先贴在这里,等我学会了再回来看看
function leftPad(n, len){
len = len || 2;
n = n + '';
var diff = len - n.length;
if (diff > 0) {
n = new Array(diff + 1).join('0') + n;
}
return n;
}
function leftpad (str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) ch = ' ';
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}

然后是倒计时的代码:

方法一:

单例模式,简单方便好理解,缺点是每次init都会拿一个新定时器,性能不好。继承和扩展能力一般,无法获取实例属性,导致了执行状态都是不可见的。

var CountDown = {
$ : function(id){/*id选择器*/},
init :function(startTime,endTime,el){/*执行定时器入口,使用setTimeout调用_timer*/},
_timer : function(startTime,endTime,el){/*私有方法,处理时间参数等具体业务*/}
}
CountDown.init("","2016,04,23 9:34:44","countdown1");

方法二:

标准的原型构造器写法,简单方便好理解,确定是每次都拿一个新定时器,实例增多后性能同样不好,按道理setTime,leftPad等方法都可以通过继承来实现,方便扩展和复用,

prototype上的方法均为辅助方法,按理不应该被外部调用,这里应该封装为私有方法或者前缀+_,优点可以通过实例拿到相关倒计时属性,可以对实例再做扩展操作。

function Countdown(elem, startTime, endTime) {
this.elem = elem;
this.startTime = (new Date(startTime).getTime()) ? (new Date(startTime).getTime()) : (new Date().getTime());
this.endTime = new Date(endTime).getTime();
}
Countdown.prototype = {
SetTime: function() {},
leftPad: function(n) {},
DownTime: function() {}
}
var test = new Countdown("time", "2016/1/30,12:20:12", "2017/1/30,12:20:12");
test.SetTime();

方法三:

优点:这里的countdown是一个比较简单的工厂模式实现,实现了一个统一的create方法,create方法上调用了style这个属性上扩展的样式(style1-3)实现,

create方法返回的是一个独立的新实例,并统一扩展了go方法,go方法里统一创建定时器并挂载到timer属性,在这里我们也就等同拥有了修改和控制每个工厂造出来的单例的能力,

样式做到了可扩展,leftPad,timeToSecond也可以方便通过一个utils对象来进行继承。

缺点:没有考虑到上面提到的setTimeout和setInterval的区别,也没有时间校验机制,在性能方面考虑不多。

var countdown = {};
countdown.leftPad = function(n, len) {};
countdown.timeToSecond = function(t) {};
/**
* 倒计时工厂
* @param {[object]} obj 倒计时配置信息
* @return {[object]} 返回一个倒计时对象
*/
countdown.create = function(obj) {
var o = {};
o.dom = document.getElementById(obj.id);
o.startMS = +new Date(obj.startTime || 0);
o.endMS = +new Date(obj.endTime || 0);
obj.totalTime && (o.totalTime = countdown.timeToSecond(obj.totalTime)); var newCountdown = new countdown.style[obj.style](o); newCountdown.go = function(callback) {
callback && (newCountdown.callback = callback);
newCountdown.render();
clearInterval(newCountdown.timer);
newCountdown.timer = setInterval(newCountdown.render, 1000);
};
return newCountdown;
};
countdown.style.style1 = function(obj) {
this.dom = obj.dom;
this.startMS = obj.startMS;
this.endMS = obj.endMS;
var _this = this;
this.render = function() {
var currentMS = +new Date();
var diff = (_this.endMS - currentMS) / 1000;
var d = parseInt(diff / 60 / 60 / 24);
d = countdown.leftPad(d, 3);
d = d.replace(/(\d)/g, '<span>$1</span>');
_this.dom.innerHTML = '距离国庆节还有:' + d + '天';
if (currentMS > _this.endMS) {
clearInterval(_this.timer);
if (_this.callback) {
_this.callback();
} else {
_this.dom.innerHTML = '国庆节倒计时结束';
}
}
};
};
countdown.style.style2 = function(obj) {};
countdown.style.style3 = function(obj) {};
countdown.create({id:"clock3",totalTime:'82:23',style:'style1'}).go(function(){alert('It is over');});

以上是我在社区里看到的前几个例子,后面的几个例子已经是我看不懂的阶段了。。。所以就不贴在这里了,先保存记录,然后再慢慢学习

自己的程序员之路还有很远要走。。。

by新手小白的纪录

setTimeout和setInterval的区别以及如何写出效率高的倒计时的更多相关文章

  1. setTimeout与setInterval的区别

    setTimeout与setInterval的区别:1.setTimeout设置后隔指定时间后只会执行一次2.setInterval设置后会每隔指定时间执行一次3.setTimeout一般在方法内部使 ...

  2. setTimeout()和setInterval()的区别

    JS学习 - setTimeout()和setInterval()的区别 相同点 setTimeout 和 setInterval的语法相同.他们都有两个参数,一个是将要执行的代码字符串,还有一个是以 ...

  3. javascript中的两个定时函数setTimeOut()和setInterVal()的区别

    js中经常性要用到间隔几秒或暂停几秒执行某个函数, 简单介绍我从网上收集到setTimeOut()和setInterVal()的区别1.setInterVal()介绍 1)定义 setInterval ...

  4. Javascript中setTimeout和setInterval的区别和使用

    在javascript中,window对象有两个主要的定时方法,分别是setTimeout 和 setInterval,其语法基本上相同,但是完成的功能取有区别. setTimeout方法是定时程序, ...

  5. setTimeout()与setInterval()方法区别介绍

    计时器setTimeout()和setInterval()两个都是js的计时功能的函数两个有些区别,下面为大家简单介绍下,希望对大家有所帮助   计时器setTimeout()和setInterval ...

  6. setTimeout和setinterval的区别

    setTimeout("alert('久等了')",2000)是等待多长时间开始执行函数 setinterval(fn,1000)是每隔多长时间执行一次函数 setTimeout和 ...

  7. JavaScript中setTimeout()和setInterval()的区别

    含义: setTimeout()和setInterval()经常被用来处理延时和定时任务.使用setTimeout()处理延时任务,而使用setInterval()方法处理定时任务: setTimeo ...

  8. setTimeout 和 setInterval 的区别

    setTimeout (表达式,延时时间)setInterval(表达式,交互时间)延时时间/交互时间是以豪秒为单位的(1000ms=1s) setTimeout   在执行时,是在载入后延迟指定时间 ...

  9. setTimeout 与setInterval的区别

    setTimeout(code,millisec) 方法用于在指定的毫秒数后调用函数或计算表达式 setInterval(code,millisec) 方法可按照指定的周期(以毫秒计)来调用函数或计算 ...

随机推荐

  1. 2.1 C#的关键字

    关键字是被C#规定了用途的重要单词.在visual studio中,关键字以蓝色字体显示.图中红色方框圈起来的就是关键字. 关键字 class ,这个关键字的用途是声明类.比如上面例子中,类名叫做Pr ...

  2. SecureCRT:保存输出日志的方法

    处理地址: http://blog.sina.com.cn/s/blog_64c1dd210101gzgz.html 或者: http://renchen.blog.51cto.com/4531967 ...

  3. FastJson转换自定义枚举类

    在项目中有些状态需要采用枚举类型,在数据库中保存的是name(英文),而前台需要显示的是text(中文). 所以这就需要自己去实现序列. 例如对象: import java.util.Date; im ...

  4. wx getlocation

    http://www.cnblogs.com/txw1958/p/weixin-web-location.html http://blog.csdn.net/myfmyfmyfmyf/article/ ...

  5. ORA-12537: TNS:connection closed

    http://www.vitalsofttech.com/ora-12537-tnsconnection-closed/ Question: When trying to establish a sq ...

  6. Linux:-杀进程的技巧

    <---kill进程的技巧---> 1.杀掉某个关键字的进程 pgrep -f 2.批量杀掉某个关键字的进程 pkill - "name" 3.批量杀掉多个关键字的进程

  7. JSON总结

    JSON:  关于JSON,最重要的是要理解它是一种数据格式,不是一种编程语言.虽然JSON与JavaScript具有相同的语法形式与JSON具有相同的语法形式,但JSON并不从属于JavaScrip ...

  8. svn: 期望文件系统格式在“1”到“4”之间;发现格式“6”

    svn 客户端浏览的时候出现了这个提示,经查,发现是Subversion 1.7 < TortoiseSVN 1.8导致的,需要更换版本,应该是 Version(Subversion) > ...

  9. SAML 2.0 setup steps, 效果图

    Steps of setting up SAML SSO. 效果图 # Registry a Identity Provider services in:(Might need purchase) I ...

  10. easyUI + swfupload 多附件上传功能

    public void UPLOADFILED() { Date dt = new Date(System.currentTimeMillis()); SimpleDateFormat sdf = n ...