为何MDN闭包for循环示例共享变量但自定义测试变量独立
核心差异本质:闭包捕获的变量所属的作用域不同
1. MDN示例的变量作用域逻辑
- 你用
var声明item时,var只有函数级作用域,没有块级作用域,所以整个setupHelp函数里只有唯一的一个item变量 - 循环的每一轮都是给这个全局唯一的
item重新赋值,三个onfocus回调作为闭包,捕获的都是同一个item的引用 - 等你触发focus事件时,循环早就执行完了,
item已经被赋值为helpText的最后一项,所以所有回调都拿到最后一条帮助文本
2. 你的测试代码的变量作用域逻辑
- 你每次调用
closure()函数时,都会在本次closure的函数作用域内,创建一个全新的独立的i变量 a对应的闭包来自第一次closure()调用,捕获的是第一个i;b对应的闭包来自第二次closure()调用,捕获的是第二个i- 两个
i属于完全独立的函数作用域,互不干扰,自然修改一个不会影响另一个
常见修复方案
如果要让MDN的示例符合预期,有两种常用方法:
方法1:用let替代var声明循环变量
let有块级作用域,每轮循环都会创建一个独立的item变量,每个回调捕获的是当前轮次的独立item:
for (var i = 0; i < helpText.length; i++) { let item = helpText[i]; // 每轮循环创建新的item document.getElementById(item.id).onfocus = function() { showHelp(item.help); } }
方法2:用立即执行函数(IIFE)创建独立作用域
每轮循环把当前item作为参数传入IIFE,生成独立的作用域保存当前值:
for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; (function(currentItem) { document.getElementById(item.id).onfocus = function() { showHelp(currentItem.help); } })(item) }
内容的提问来源于stack exchange,提问作者khuongduy354
相关产品推荐
相关产品推荐

