let和var特性去了解闭包问题的特性
下列代码输出结果为?
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
。
这也侧面反应了闭包问题的特性就是,优点是能够更新新的数据,
但是缺点是,不利于去存储迭代的数据。且内存消耗:由于闭包保留了对外部作用域的引用,它们可能导致内存泄漏问题,特别是当闭包的生命周期比外部函数长时。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义