为何调用clock.stop()无法终止clock.start()启动的定时器?
定时器无法停止的原因与修复方案
你碰到的这个问题其实很常见,核心是**setTimeout回调里的this指向不对**,导致你调用clearInterval(this._timer)时,根本没拿到正确的定时器ID,所以定时器才会继续跑。
问题根源拆解
在你的stop方法里,setTimeout的回调函数执行时,默认情况下this指向的是全局对象(浏览器环境里就是window),而不是你的Clock实例对象。所以这里的this._timer其实是undefined,调用clearInterval(undefined)完全起不到终止定时器的作用——这就是为什么你能看到Stop!的日志,但定时器还在运行的原因。
三种修复方案
你可以用以下任意一种方式来修正this的指向:
1. 提前保存this到变量(和start方法的写法一致)
这是最传统也最稳妥的方式,把当前实例的this存到一个变量里,在回调里用这个变量访问实例:
Clock.prototype.stop = function() { var self = this; // 保存当前Clock实例的引用 setTimeout(function() { clearInterval(self._timer); console.log('Stop!'); }, 5000); };
2. 使用箭头函数(ES6+)
箭头函数不会创建自己的this,它会继承外层作用域的this,也就是stop方法执行时的Clock实例:
Clock.prototype.stop = function() { setTimeout(() => { clearInterval(this._timer); console.log('Stop!'); }, 5000); };
3. 用bind绑定this
通过bind方法把回调函数的this绑定为当前的Clock实例:
Clock.prototype.stop = function() { setTimeout(function() { clearInterval(this._timer); console.log('Stop!'); }.bind(this), 5000); };
验证效果
把上面任意一种方案替换原有的stop方法后,5秒后clearInterval就能正确拿到start方法里保存的定时器ID,从而成功终止定时器。
内容的提问来源于stack exchange,提问作者Sviat Kuzhelev
相关产品推荐
相关产品推荐

