REC

JavaScript 循环中的闭包陷阱:“意料之外” 的共享

易航
2月20日发布

闭包 (Closure) 无疑是 JavaScript 中最强大、最迷人的特性之一。它赋予了函数访问其定义时所在词法环境的能力,即使该函数在其定义的作用域之外执行。凭借闭包,我们可以实现数据封装、模块化、柯里化等高级编程技巧。

然而,硬币的另一面是,闭包也常常被视为 JavaScript 中最容易误解、最容易出错的特性之一。稍有不慎,就会掉入闭包的“陷阱”,导致内存泄漏、意外的变量共享等问题。

图片[1] - JavaScript 循环中的闭包陷阱:“意料之外” 的共享 - 易航博客

在循环中使用闭包时,很容易出现意外的变量共享问题。

图片[2] - JavaScript 循环中的闭包陷阱:“意料之外” 的共享 - 易航博客

在这个例子中,我们期望 setTimeout 的回调函数(闭包)分别输出 0, 1, 2, 3, 4。但实际输出的却是 5 次 5。这是因为 setTimeout 是异步执行的,当回调函数执行时,循环已经结束,i 的值已经变成了 5。而且,由于使用了 var 声明 i,所有的回调函数共享的是同一个 i 变量。

解决方法:

使用 let 声明循环变量:let 具有块级作用域,每次循环都会创建一个新的 i 变量,避免了变量共享。
图片[3] - JavaScript 循环中的闭包陷阱:“意料之外” 的共享 - 易航博客

使用立即执行函数 (IIFE):创建一个立即执行函数,将循环变量 i 作为参数传递进去,形成一个闭包,每次循环都会创建一个新的作用域。
图片[4] - JavaScript 循环中的闭包陷阱:“意料之外” 的共享 - 易航博客

使用bind方法:使用 bind 方法将循环变量 i 绑定到回调函数上。
图片[5] - JavaScript 循环中的闭包陷阱:“意料之外” 的共享 - 易航博客

© 版权声明
转载本网站任何内容,请按照转载方式正确书写本站原文地址。
THE END
喜欢就支持一下吧
点赞 0 分享 赞赏
评论 抢沙发
OωO
取消 登录评论