下列代码输出结果为?
for(var i = 0; i < 3; i++){
setTimeout(function(){
console.log(i); },0);
};
输出结果是:3,3,3
为什么不是0,1,2呢?
如果换成
for (var i = 0; i < 3; i++) { (function(i) {
setTimeout(function () {
console.log(i); }, 0, i)
})(i) };
就可以输出012
主要原因是setTimeout是异步函数,所以他会在最后再去获取i,var和let的特性不同,var是函数作用域,而let是块级作用域,使用 var
声明 i
时,i
具有函数作用域,而且它是在全局范围内声明的。
因此,在循环结束后,i
的值变成了 3。而用let去声明变量的时候,每次迭代的时候都会去创建一个新的变量i去存储,所以能够输出012。
使用var去定义,是一个典型的闭包问题,让我解释一下为什么这是闭包:
-
在
for
循环中,你使用了var
声明了变量i
,这将使i
具有函数作用域。 -
在
setTimeout
的回调函数内部,它引用了变量i
。即使setTimeout
是异步执行的,它仍然可以访问和引用for
循环中的i
变量。 -
当
setTimeout
的回调函数执行时,它访问的是外部函数作用域中的i
变量,而不是在函数内部声明的i
。
这也侧面反应了闭包问题的特性就是,优点是能够更新新的数据,
但是缺点是,不利于去存储迭代的数据。且内存消耗:由于闭包保留了对外部作用域的引用,它们可能导致内存泄漏问题,特别是当闭包的生命周期比外部函数长时。
标签:闭包,函数,作用域,特性,let,var,setTimeout From: https://www.cnblogs.com/Ly021/p/17729051.html