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. REM 布局

    1.rem是什么? rem(font size of the root element)是指相对于根元素的字体大小的单位 2.为什么web app要使用rem? 实现强大的屏幕适配布局(淘宝,腾讯,网 ...

  2. vue.js 批量删除跟全选,反选效果

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  3. CSS生成内容

    在Web中插入内容,在CSS2.1时代依靠的是JavaScript来实现.但进入CSS3进代之后我们可以通过CSS3的伪类“:before”,“:after”和CSS3的伪元素“::before”.“ ...

  4. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  5. sklearn 增量学习 数据量大

    问题 实际处理和解决机器学习问题过程中,我们会遇到一些"大数据"问题,比如有上百万条数据,上千上万维特征,此时数据存储已经达到10G这种级别.这种情况下,如果还是直接使用传统的方式 ...

  6. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  7. win2008使用FireDac连接ORACLE数据库问题

    2008上装DELPHI XE7,无论用FireDac 还是Ado都连不上ORACLE数据库 --------------------------- Debugger Exception Notifi ...

  8. IISExpress 调试使用学习,使用附加到进程进行快速调试

    IIS8.0 Express已经推出了,大家可以通过Microsoft Web Platform Installer 进行安装.(VS2012,VS2013已经内置了,不需安装了) 1.IIS Exp ...

  9. ajax 如何接受 PHP页面返回的json数组

    JSON JSON(JavaScript Object Notation)是Douglas Crockford提出的.他是一个轻量级的数据交换格式,基于JavaScript对象字面量. 我们可以将之前 ...

  10. percona server 二进制安装下编译tpcc-mysql的坑

    出于习惯,percona server的部署都是通过二进制包自动化安装,结果遇到一个硕大无比的坑,编译TPCC-MySQL时出现警告 10:49:36 root@DB-Master:~/tpcc-my ...