setTimeout与setInterval

作用域问题

由setTimeout()/setInterval()调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的this关键字在非严格模式会指向window(或global)对象,严格模式下为undefined,这和所期望的this的值是不一样的。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Swiper(num, loopTime) {
this.num = num;
this.loopTime = loopTime;
this.timer = null;
this.autoPlay();
}
Swiper.prototype.autoPlay = function() {
clearInterval(this.timer);
this.timer = setInterval(this.loop, this.loopTime);
}
Swiper.prototype.loop = function() {
console.log('num', this.num);
this.num++;
}
var swiper = new Swiper(0, 1000);

我们期望得到的是0,1,2,…但是实际上是undefined,NaN,NaN,…这是因为this的指向问题,执行this.loop函数时,里面的this是全局变量window,由于num未在全局中初始化,所以第一个值是undefined,之后进行++运算时,undefined转换为Number类型时是NaN,故自然就是上面的那个结果了。

解决方法

1:闭包

1
2
3
4
5
6
7
Swiper.prototype.autoPlay = function() {
clearInterval(this.timer);
var self = this;//将this对象保存在self中
this.timer = setInterval(function(){
self.loop();
},this.loopTime);
}

2:ES5中Function.prototype.bind方法

1
2
3
4
Swiper.prototype.autoPlay = function() {
clearInterval(this.timer);
this.timer = setInterval(this.loop.bind(this), this.loopTime);
}

3:ES6中的箭头函数

1
2
3
4
5
6
Swiper.prototype.autoPlay = function() {
clearInterval(this.timer);
this.timer = setInterval(() => {
this.loop();
},this.loopTime);
}

参考链接:http://qingbob.com/difference-between-settimeout-setinterval/
https://juejin.im/entry/59e96a7bf265da432f303d4c