javascript 避免闭包引发的问题


Posted in Javascript onMarch 17, 2009

<div id="test">
<div>第一个</div>
<div>第二个</div>
<div>第三个</div>
<div>第四个</div>
</div>
<script>
function test()
{
var els = document.getElementById("test").getElementsByTagName("div");
for (var i = 0; i < els.length; i++)
{
var div = els[i];
div.onclick = function()
{
alert(div.innerHTML);
return false;
}
}
}
test();
</script>
无论我们点击哪个div,反馈的都是第4个div的内容。究其原因,在于每个div的点击事件都与test方法形成了闭包,且每个div的点击事件都共享同一个闭包作用域链。当事件被触发时,变量i所代表的下标已经指向第4个div。可以采用以下几种方式避免由于闭包引起的问题。
(1)使用this转换闭包的作用域链上下文,上例的闭包可以改写为:
for (var i = 0; i < els.length; i++)
{
var div = els[i];
div.onclick = function()
{
alert(this.innerHTML);
return false;
}
}
当点击div的事件被触发时,查找的作用域已经是“this”所指定的上下文。尽管该事件仍然处于“test”闭包内,但由于不访问或不使用闭包的上下文环境,也就不存在由于闭包作用域内变量被引用所引发的问题。
(2)使点击div的事件与for循环形成闭包,而使得for循环内的变量div不被回收。如:
//for循环内定义闭包方法
for (var i = 0; i < els.length; i++)
{
var div = els[i];
a(div);
function a(o)
{
o.onclick = function()
{
alert(o.innerHTML);
}
}
}
//for循环外定义闭包方法
for (var i = 0; i < els.length; i++)
{
var div = els[i];
a(div);
}
function a(o)
{
o.onclick = function()
{
alert(o.innerHTML);
}
}
//使用匿名方法,其原理与for循环内定义类似
for (var i = 0; i < els.length; i++)
{
var div = els[i];
(function(o)
{
o.onclick = function()
{
alert(o.innerHTML);
}
})(div);
}
通过中间方法a或者匿名方法,使for循环体与onclick事情产生闭包。
(3)控制变量的作用域,使点击div的事件所需变量与外层作用域无关。如:
for (var i = 0; i < els.length; i++)
{
(function()
{
var div = els[i];
div.onclick = function()
{
alert(div.innerHTML);
}
})();
}
内部函数自身也可能有内部函数。每次作用域链嵌套,都会增加由创建内部函数对象的执行环境所引发的新活动对象。ECMA262规范要求作用域链是临时性的,但对作用域链的长度却没有加以限制。闭包的潜规则即Function与内部定义的Function之间的相互作用域链上下文环境的关系。如果运用得当,嵌套的内部函数所拥有的潜能将超出了我们的想象力。

Javascript 相关文章推荐
基于jQuery中对数组进行操作的方法
Apr 16 Javascript
怎么选择Javascript框架(Javascript Framework)
Nov 22 Javascript
js实现弹窗插件功能实例代码分享
Dec 12 Javascript
node.js [superAgent] 请求使用示例
Mar 13 Javascript
javascript封装 Cookie 应用接口
Aug 07 Javascript
教你用javascript实现随机标签云效果_附代码
Mar 16 Javascript
JQ选择器_选择同类元素的第N个子元素的实现方法
Sep 08 Javascript
微信小程序 for 循环详解
Oct 09 Javascript
jQuery与JavaScript节点创建方法的对比
Nov 18 Javascript
js实现带进度条提示的多视频上传功能
Dec 13 Javascript
详解Vue源码中一些util函数
Apr 24 Javascript
echarts实现获取datazoom的起始值(包括x轴和y轴)
Jul 20 Javascript
用JavaScript编写COM组件的步骤
Mar 17 #Javascript
IE6与IE7中,innerHTML获取param的区别
Mar 15 #Javascript
InnerHtml和InnerText的区别分析
Mar 13 #Javascript
JavaScript 快捷键设置实现代码
Mar 13 #Javascript
JavaScript 事件属性绑定带参数的函数
Mar 13 #Javascript
自动完成JS类(纯JS, Ajax模式)
Mar 12 #Javascript
动态添加js事件实现代码
Mar 12 #Javascript
You might like
PHP中spl_autoload_register函数的用法总结
2013/11/07 PHP
js设置cookie过期及清除浏览器对应名称的cookie
2013/10/24 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
jQuery表单美化插件jqTransform使用详解
2015/04/12 Javascript
Javascript闭包(Closure)详解
2015/05/05 Javascript
jQuery构造函数init参数分析
2015/05/13 Javascript
VUEJS实战之利用laypage插件实现分页(3)
2016/06/13 Javascript
JS实现双击内容变为可编辑状态
2017/03/03 Javascript
JS实现问卷星自动填问卷脚本并在两秒自动提交功能
2020/06/17 Javascript
js匿名函数使用&amp;传参(实例)
2017/09/08 Javascript
jQuery 开发之EasyUI 添加数据的实例
2017/09/26 jQuery
BootStrap模态框不垂直居中的解决方法
2017/10/19 Javascript
Angular路由ui-router配置详解
2018/08/01 Javascript
Nodejs监听日志文件的变化的过程解析
2019/08/04 NodeJs
node.js express框架实现文件上传与下载功能实例详解
2019/10/15 Javascript
nodemon实现Typescript项目热更新的示例代码
2019/11/19 Javascript
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
element日历calendar组件上月、今天、下月、日历块点击事件及模板源码
2020/07/27 Javascript
使用python实现拉钩网上的FizzBuzzWhizz问题示例
2014/05/05 Python
Python中下划线的使用方法
2015/03/27 Python
解决Python 命令行执行脚本时,提示导入的包找不到的问题
2019/01/19 Python
Python 使用type来定义类的实现
2019/11/19 Python
用Python实现校园通知更新提醒功能
2019/11/23 Python
numpy中三维数组中加入元素后的位置详解
2019/11/28 Python
python实现mask矩阵示例(根据列表所给元素)
2020/07/30 Python
python 如何在测试中使用 Mock
2021/03/01 Python
微信html5页面调用第三方位置导航的示例
2018/03/14 HTML / CSS
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
临床医学专业毕业生的自我评价
2013/10/17 职场文书
毕业生个人的求职信范文
2013/12/03 职场文书
市场部业务员岗位职责
2014/04/02 职场文书
开除通知书范本
2015/04/25 职场文书
优化经济发展环境工作总结
2015/08/11 职场文书
Python爬虫进阶之Beautiful Soup库详解
2021/04/29 Python
Python爬虫之自动爬取某车之家各车销售数据
2021/06/02 Python
ORACLE中dbms_output.put_line输出问题的解决过程
2022/06/28 Oracle