最近面试常常碰到这样一道题(或者相似):ps.由于我阿姨不会就详细分析吧。es6
var btns = document.getElementsByClassName('btn'); for(let i = 0; i < btns.length; i++){ btn[i].onclick = function(){ console.log(i) } }
这个以前说过,由于面试的时候,说了主要看闭包。因此也没有多想。面试
function fun(){ for (var i = 0; i < 5; i++){ setTimeout(()=>{ console.log(i) },0); } } fun();
其实,经过分析就不难看出,核心点问题都是, 在一个循环内,延时打印循环变量。 全部的结果同样。promise
由于js的变量有提高做用,因此能够将程序改为成更加直观的形式。闭包
var i = 0; function fun(){ while (i < 5){ setTimeout(()=>{ console.log(i) // 这里访问的i 都是 以前定义的 i },1000); i++; // 这里访问的i 也是 以前定义的 i } } fun();
咱们改为程序以后,就能够看到了。 打印语句的i,由于都是在等待i变换以后,取i值打印, 因此结果同样。函数
这里产生问题的缘由在于:code
其实,核心问题,就是等待循环结束,才去访问i,并且访问的是同一个i。
解决思路:两种 改变访问时机, 改变访问变量。作用域
for( var i = 0; i < 5; i++){ console.log(i); }
这样作好像没什么意义。get
function fun(){ for (let i = 0; i < 5; i++){ setTimeout(()=>{ console.log(i) },0); } } fun();
用let代替var来声明变量,就能够把变量的做用域限制在当前代码块中也就是{}io
function fun(){ for (var i = 0; i < 5; i++){ setTimeout((function(i_){ return function(){ console.log(i_) } })(i),0); } } fun();
其实, 也就是用 当即执行函数参数i_ 来保存 i 值 。 固然你也能够把i_写成i。console
分割线(这对以前问题的处理)
function fun(){ for (var i = 0; i < 5; i++){ var promise = new Promise(function(resolve, reject){ setTimeout(resolve,1000,i); }); // 这个是当即执行 promise.then(function(value){ // 回调执行 console.log(value); }) } } fun();
下面代码也能够实现,其实,你就会发现, 这是由于 setTimeout 函数 能够调用给函数传递参数的缘由, 。
function fun(){ for (var i = 0; i < 5; i++){ setTimeout((i)=>{ console.log(i) },0,i); } } fun();