JavaScript—在循环中创建闭包:一个常见错误
2017-03-05 10:21
501 查看
在循环中创建闭包:一个常见错误EDIT
在 JavaScript 1.7 引入 let关键字 之前,闭包的一个常见的问题发生于在循环中创建闭包。参考下面的示例:
<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列表中的最后一项。
解决这个问题的一种方案是使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数组中对应的字符串。
相关文章推荐
- 深入理解JavaScript - 闭包 (四)常见的一个循环和闭包的错误详解
- 深入理解闭包系列第四篇——常见的一个循环和闭包的错误详解
- JavaScript闭包常见错误:在循环中创建闭包
- 深入理解闭包系列第四篇——常见的一个循环和闭包的错误详解
- js的一个有意思的小题,闭包解决getElementByTagName的for循环绑定事件错误问题
- for循环一个常见的错误(c++primer 3.13题)
- JavaScript 闭包 之 依次循环每一秒 alert 数组中的一个值
- 关于闭包一个常见的错误
- 解决JavaScript脚本出"Antomation服务器不能创建对象"的错误
- 创建ASP.NET程序时候发生错误"HTTP/1.0 500 Server Error"的一个解决办法
- 一个常见数据库操作错误的分析(四)
- javascript常见错误解释
- 用javascript 创建ActiveX对象时出现:Automation server can't create object"(Automation 服务器不能创建对). 错误的解决办法。
- javascript 常见错误(失误足迹)
- Javascript常犯的一个错误
- 使用JAVASCRIPT动态创建一个Select元素
- ASP.NET的DropDownList控件OnSelectedIndexChanged事件产生Javascript错误的一个原因
- 使用JavaScript创建一个字符串对象
- 一个常见数据库操作错误的分析(二)
- 使用JavaScript创建一个字符串对象