JavaScript闭包常见错误:在循环中创建闭包
来源:互联网 发布:弹弹123网络连接错误 编辑:程序博客网 时间:2024/06/05 18:10
1.错误示例
<p id="help">Helpful notes will appear here</p><p>E-mail: <input type="text" id="email" name="email"></p><p>Name: <input type="text" id="name" name="name"></p><p>Age: <input type="text" id="age" name="age"></p>
function showHelp(help) { document.getElementById('help').innerHTML = help;}function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } }}setupHelp();
数组 helpText 中定义了三个有用的提示信息,每一个都关联于对应的文档中的输入域的 ID。通过循环这三项定义,依次为每一个输入域添加了一个 onfocus 事件处理函数,以便显示帮助信息。
运行这段代码后,您会发现它没有达到想要的效果。无论焦点在哪个输入域上,显示的都是关于年龄的消息。
该问题的原因在于赋给 onfocus是闭包(setupHelp)中的匿名函数而不是闭包对象;在闭包(setupHelp)中一共创建了三个匿名函数,但是它们都共享同一个环境(item)。在 onfocus 的回调被执行时,循环早已经完成,且此时 item 变量(由所有三个闭包所共享)已经指向了 helpText 列表中的最后一项。
2.解决办法1:使onfocus指向一个新的闭包对象。
function showHelp(help) { document.getElementById('help').innerHTML = help;}function makeHelpCallback(help) { return function() { showHelp(help); };}function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = makeHelpCallback(item.help); }}setupHelp();
这段代码可以如我们所期望的那样工作。所有的回调不再共享同一个环境, makeHelpCallback 函数为每一个回调创建一个新的环境。在这些环境中,help 指向 helpText 数组中对应的字符串。
3.解决办法2:使用匿名闭包
function showHelp(help) { document.getElementById('help').innerHTML = help;}function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ]; for (var i = 0; i < helpText.length; i++) { (function() { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } })(); // Immediate event listener attachment with the current value of item (preserved until iteration). }}setupHelp();
4.解决办法3:用let关键词
function showHelp(help) { document.getElementById('help').innerHTML = help;}function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ]; for (var i = 0; i < helpText.length; i++) { let item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } }}setupHelp();
用let而不用var,使得每个闭包绑定块内变量,不需要额外的闭包。
阅读全文
0 0
- JavaScript闭包常见错误:在循环中创建闭包
- JavaScript—在循环中创建闭包:一个常见错误
- 【JavaScript】在循环内使用闭包
- JavaScript 闭包 for循环
- javascript循环与闭包
- JavaScript闭包中的循环
- 在Javascript中,什么是闭包(Closure)
- 在Javascript中,什么是闭包(Closure)
- 在Javascript中,什么是闭包(Closure)
- 在Javascript中,什么是闭包(Closure)
- 在Javascript中,什么是闭包
- javascript中循环加载监听事件的闭包问题
- 循环中使用闭包
- 在SSIS中,使用“包配置”时的常见错误
- 再谈javascript闭包--Javascript高级用法 ----在Javascript中,什么是闭包(Closure)
- Javascript利用闭包循环绑定事件
- JavaScript闭包 取for循环i
- JavaScript--------闭包 取for循环i
- 入门级----需求的分析以及测试用例的设计与编写
- NIO详解一
- 安卓学习记录——(2.界面布局)
- Python 练习 人民币金额打印
- sphinx php扩展安装
- JavaScript闭包常见错误:在循环中创建闭包
- CSDN-文件搜索
- JavaScript同步加载和异步加载
- C语言之各种运算符
- NIO详解二
- LevelDbHelper.cs
- Linux程序分析工具:ldd和nm
- sqlite数据库加密方案
- 为什么(什么时候)使用Redux?(三张图)