js中this作用域引发的惨案

function MultiTimeOut(count, timer, cb){
	var c = count > 1 ? count : 1
	var s = false
	
	this.run = function(){
		if(c > 0 && !s){
			cb()
			c--
			setTimeout(this.run, timer)
		}
	}
	 
	this.stop = function(){
		s = true
	}
	
	this.reset = function(){
		c = 1
		s = false
	}
}

  

先看这段代码吧,定义了一个构造函数,在函数中指定重复次数,时间间隔和回调函数(要执行的操作),调试中却发现无论count设置成多少,回调函数都只能执行2次,妈蛋~~从函数定义到调用看了一遍又一遍,逻辑似乎没问题,调用方法也没错,那问题到底出在哪里呢?

聪明如你,估计已经从标题猜出了什么~~

没错,在run函数中打印this,第一次指向的是MultiTimeOut自身,符合初衷,但第二次打印出来,这个this却指向了window对象,这是this.run=window.run,但页面中并未定义run方法,所以这时的this.run=undefined,函数自然就在这里终止无法进行下去了

找到问题就好解决了,既然是this的问题,那就换个思路,this的作用域会转移,那就在函数内部维护一个变量指向函数本身不就可以了吗,本着这个思路,修改代码


function MultiTimeOut(count, timer, cb){
	var c = count > 1 ? count : 1
	var s = false
	var cc = this
	
	this.run = function(){
		if(c > 0 && !s){
			cb()
			c--
			setTimeout(cc.run, timer)
		}
	}
}


测试通过!


在这个问题上浪费了两个小时的时间,说到底还是对变量作用域这些基础知识掌握的似是而非不够扎实,出现问题也未能使用有效手段快速定位问题,矫情话没啥好说,趁着最近正在研究nodejs的机会,把js的语法基础好好学习和梳理一下。


-----------------------------------

重写了这部分代码,测试通过,如下:

var MultiTimeOut = {
	creatNew: function(count, timer, cb){
		var mto = {}
		var to = 0
		var s = false
		
		mto.run = function(){
			cb()
			if(to < count){
				to = setTimeout(mto.run, timer)
			}			
		}
		
		mto.end = function(){
			clearTimeout(to)
		}
		return mto
	}
}


你可能感兴趣的:(JavaScript)