jQuery循环绑定keyup事件月度收入字段计算异常原因求解
问题原因
这是JavaScript经典的循环闭包变量作用域问题,根本原因如下:
- 你循环中使用的
month变量(对应你省略的month = actualMonths[i]赋值逻辑)是用var声明的,不存在块级作用域,整个循环过程中所有事件回调共享同一个month变量的引用,不会每次循环生成独立的变量副本。 - keyup事件回调是异步触发的,只有用户操作输入框时才会执行回调代码,此时循环早已执行完毕,
month变量已经被更新为循环结束后的最终值12,所以所有回调读取到的都是同一个最终值。 - 额外注意:id选择器本身是全局唯一的,不需要加
input前缀,直接写#month-revenue-xx即可,选择器执行效率更高。
解决方案
下面提供3种不同场景的可行方案:
方案1:使用let声明块级作用域变量(ES6+环境推荐)
用let声明循环内的月份变量,每次循环会生成独立的块级作用域变量,回调会绑定当前循环的变量值:
for (let i=0; i < actualMonths.length; i++) { let month = actualMonths[i]; $('#month-revenue-'+month).keyup(function(){ const revenue = $(this).val(); const margin = $('#month-margin-'+month).val(); let value = (margin / 100) * revenue; value = value.toLocaleString("en-US"); $('#month-price-'+month).html(value); }); }
方案2:立即执行函数创建独立作用域(兼容ES5旧环境)
如果需要兼容不支持ES6的旧浏览器,可以用立即执行函数把每次循环的月份值封存在独立的函数作用域中:
for (var i=0; i < actualMonths.length; i++) { var month = actualMonths[i]; (function(curMonth) { $('#month-revenue-'+curMonth).keyup(function(){ var revenue = $(this).val(); var margin = $('#month-margin-'+curMonth).val(); var value = (margin / 100) * revenue; value = value.toLocaleString("en-US"); $('#month-price-'+curMonth).html(value); }); })(month); }
方案3:事件委托+动态提取月份(更易维护的写法)
不需要循环绑定事件,直接用事件委托绑定父容器,触发时从当前元素ID提取月份值,后续新增月份字段不需要修改绑定逻辑:
// 把#month-form替换为你实际存放所有月份输入框的父容器选择器 $('#month-form').on('keyup', 'input[id^="month-revenue-"]', function() { const month = this.id.replace('month-revenue-', ''); const revenue = $(this).val(); const margin = $('#month-margin-'+month).val(); let value = (margin / 100) * revenue; value = value.toLocaleString("en-US"); $('#month-price-'+month).html(value); });
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

