setTimeout和setInterval
javascript都是以单线程的方式运行于浏览器的javascript引擎中的,
setTimeout和setInterval的作用只是把你要执行的代码在你设定的一个时间点插入js引擎维护的一个代码队列中
以下方法都是window对象的方法:
setTimeout() 和 clearTimeout()
setInterval() 和 clearInterval()
一、使用时注意作用域
如果需要在对象内部用定时器执行该对象的某一方法时就需要注意了
function Game () {} Game.prototype = { constructor: Game, init: function(){ clock = setInterval(function(){ this.update(); }, 500); }, update: function(){ console.log("test"); } } var game = new Game(); game.init();
上面的写法会出现 Uncaught TypeError: this.update is not a function
原因就在于 setInterval()属于window对象的方法,这里的this指代的是window对象,
而在window对象中又没有定义update方法,因此会报错
function Game () {} Game.prototype = { constructor: Game, init: function(){ var that = this; clock = setInterval(function(){ that.update(); }, 500); }, update: function(){ console.log("test"); } } var game = new Game(); game.init();
这样写就没有任何问题了,var that = this;这句话的意思是用that将Game对象保存起来,
再执行that.update()方法就没有任何问题了。
其实下面这样做也是可以的,只是不好传参了
function Game () {} Game.prototype = { constructor: Game, init: function(){ var that = this; clock = setInterval(that.update, 500); }, update: function(){ console.log("test"); } } var game = new Game(); game.init();
另外,使用闭包的方式也是可以的
function Game () { function update(){ console.log("test"); console.log(this);//window } setInterval(update, 500); } Game();
二、深入解析执行原理
setTimeout(callback, time)会初始化一个计时器,
在指定的时间间隔time毫秒后执行回调函数callback
setInterval(callback, time)也会初始化一个计时器,
但是它是每隔指定的时间间隔time毫秒后就循环执行回调函数callback。
如果需要连续执行某个方法有以下两种方式:
如果不希望连续调用产生互相干扰的状况就用setTimeout()嵌套,
如果希望每隔固定时间精确的执行某个动作就用setInterval()
//1. setTimeout(function() { a(); setTimeout(arguments.callee, time); }, time); //2. setInterval(function(){ a(); }, time);
举个例子:
假如执行a()方法需要10s,time等于3s,下面来分析一下两种方式的区别
1.
a()方法执行10s,那么到第一次执行callback中setTimeout的时间也是10s,执行setTimeout
函数,大概的意思就是给浏览器发个消息,“嗨哥们儿,过3s钟我要向代码队列中插入
a()方法的代码咯”,又因为callback中setTimeout方法后面并没有要执行的代码,因此这3秒
cpu其实处于空闲状态,于是再过了3s的便开始插入代码,又因为当前cpu空闲,可以立即执行
a()方法,这时时间已经到了第13s。
因此用这种方式执行一个周期所花的时间为13s
2.
由于time等于3s,按道理来讲,在3s,6s,9s时会有新的a()代码插入到代码队列中,
但是因为js引擎只允许有一份未执行的a()代码,所以真实情况并不是这样
当在前10s,a()方法正在执行期间,实际上只有3s的时候才会有新的a()代码插入
到代码队列,其它的将被忽略掉。当a()方法10s执行完毕,这时3s时插入的a()方法的代码都会开始运行。
代码插入的时间与代码执行时间其实并没有什么关系。
因此用这种方式执行一个周期所花的时间为10s
当然,这里顺便说一句,一个函数执行的时间其实并不是固定的,每次执行时间都会
有些偏差,只是大概稳定在某一个值附近罢了,这与cpu内部运行策略有关,这里扯远了