JavaScript for循环中var与let绑定点击事件输出差异原因求解
问题核心原因:var和let的作用域规则差异
1. 使用var时弹出5的原理
var声明的变量只有函数作用域/全局作用域,不存在块级作用域。本案例中var i在全局作用域声明,整个for循环全程只会共用同一个i变量,每次循环都是修改这同一个变量的值。- 给按钮绑定
onclick事件时,回调函数并没有立刻执行,函数内部只是保存了对全局i的引用,而非当前循环i的瞬时值。 - 等到循环结束时,
i已经自增到满足循环终止条件的值5,此时点击任意按钮触发回调,读取到的都是全局i的最终值5。
2. 替换为let后得到预期结果的原理
let是ES6新增的关键字,支持块级作用域。在for循环头部用let声明i时,JS会为每一轮循环都创建一个独立的i变量副本,每个副本只属于当前循环轮次的块作用域,互不干扰。- 每一轮绑定
onclick回调时,函数引用的是当前轮次独有的i变量,因此触发回调时会拿到对应轮次的索引值0~4,符合预期。
补充:ES5环境下的替代方案
如果运行环境不支持let,可以用立即执行函数(IIFE)手动为每一轮循环创建独立作用域保存当前i的值,效果和let一致:
<html> <button>Click</button> <button>Click</button> <button>Click</button> <button>Click</button> <button>Click</button> <script> var btn = document.getElementsByTagName("button"); for(var i = 0; i<5; i++){ // 每轮循环传入当前i的值,在IIFE内部创建独立的变量副本 (function(currentI) { btn[currentI].onclick = function(){alert(currentI)} })(i) } </script> </html>
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

