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 相关文章推荐
基于javascript滚动图片具体实现
Nov 18 Javascript
jquery实现多屏多图焦点图切换特效的方法
May 04 Javascript
jquery中键盘事件小结
Feb 24 Javascript
Angular2从搭建环境到开发步骤详解
Oct 17 Javascript
js中获取键盘按下键值event.keyCode、event.charCode和event.which的兼容性详解
Mar 15 Javascript
node文件上传功能简易实现代码
Jun 16 Javascript
vue之数据交互实例代码
Jun 20 Javascript
微信小程序scroll-view仿拼多多横向滑动滚动条
Apr 21 Javascript
React父子组件间的传值的方法
Nov 13 Javascript
JS实现json数组排序操作实例分析
Oct 28 Javascript
微信小程序之左右布局的实现代码
Dec 13 Javascript
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
May 13 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适配器模式介绍
2012/08/14 PHP
PHP CURL CURLOPT参数说明(curl_setopt)
2013/09/30 PHP
php cookie工作原理与实例详解
2016/07/18 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
php图片合成方法(多张图片合成一张)
2017/11/25 PHP
jquery 选择器部分整理
2009/10/28 Javascript
kmock javascript 单元测试代码
2011/02/06 Javascript
JQuery文本框高亮显示插件代码
2011/04/02 Javascript
Javascript实现前端简单的路由实例
2016/09/11 Javascript
jQuery Easyui 下拉树组件combotree
2016/12/16 Javascript
bootstrap table配置参数例子
2017/01/05 Javascript
浅谈JavaScript中的apply/call/bind和this的使用
2017/02/26 Javascript
jQuery序列化后的表单值转换成Json
2017/06/16 jQuery
Angular2+如何去除url中的#号详解
2017/12/20 Javascript
基于node搭建服务器,写接口,调接口,跨域的实例
2018/05/13 Javascript
JS实现把一个页面层数据传递到另一个页面的两种方式
2018/08/13 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
Map与WeakMap类型在JavaScript中的使用详解
2020/11/18 Javascript
Python标准库之Sys模块使用详解
2015/05/23 Python
python3 与python2 异常处理的区别与联系
2016/06/19 Python
解决Django的request.POST获取不到内容的问题
2018/05/28 Python
python标记语句块使用方法总结
2019/08/05 Python
python线程中的同步问题及解决方法
2019/08/29 Python
Python list与NumPy array 区分详解
2019/11/06 Python
python如果快速判断数字奇数偶数
2019/11/13 Python
Python实现剪刀石头布小游戏(与电脑对战)
2019/12/31 Python
解决Tensorflow sess.run导致的内存溢出问题
2020/02/05 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
CSS3的颜色渐变效果的示例代码
2017/09/29 HTML / CSS
自定义html标记替换html5新增元素
2008/10/17 HTML / CSS
统计岗位职责
2014/02/21 职场文书
企业出纳岗位职责
2014/03/12 职场文书
2014年全国法制宣传日宣传活动方案
2014/11/02 职场文书
Python爬取科目四考试题库的方法实现
2021/03/30 Python
sql中mod()函数取余数的用法
2021/05/29 SQL Server
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android