JS闭包的经典场景使用

220 阅读1分钟

在我们面试中经常遇到这么一道题

var arr = [];
for(var i = 0; i< 5; i++){      
	arr[i] = function(){           
		return i;     
	} 
}
arr[0](); // 5

这是因为在执行 for 循环的时候并没有执行函数调用,对于基本类型的调用每次都是值得拷贝,当循环执行结束的时候 i 值已经为 5. 这时,我们就可以使用闭包来做一个局部作用域的调用。

var arr = [];
for(var i = 0i5i++){      
	(function(i){
      arr[i] = function(){           
          return i;     
      } 
    })(i)
}
arr[0](); // 5

当然也可以选择用 es6 的新的变量声明方式 let 解决上述问题

var arr = [];
for(let i = 0; i< 5; i++){      
	arr[i] = function(){           
		return i;     
	} 
}
arr[0](); // 5

定时器每秒打印

var arr = [];
for(var i = 0i5i++){      
	setTimeout(() => {
    	console.log(i)
    }, i * 1000);
}

跟预想的结果不一样,打印出来了5个5,而不是1,2,3,4,5.原因相同,因为for 循环已经执行完毕,全局变量 i 已经被赋值为了 5.

闭包解决

var arr = [];
for(var i = 0i5i++){      
	(function(i){setTimeout(() => {
    	console.log(i)
    }, i * 1000)})(i);
}

同理可以使用 es6 的新的变量声明方式

var arr = [];
for(let i = 0i5i++){      
	setTimeout(() => {
    	console.log(i)
    }, i * 1000);
}