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验证只能输入数字和一个小数点示例
Oct 21 Javascript
JavaScript通过元素的ID和name设置样式
Jul 08 Javascript
jQuery中nextUntil()方法用法实例
Jan 07 Javascript
JavaScript实现表格点击排序的方法
May 11 Javascript
在Javascript中处理字符串之big()方法的使用
Jun 08 Javascript
JS实现黑客帝国文字下落效果
Sep 01 Javascript
Bootstrap3 图片(响应式图片&amp;图片形状)
Jan 04 Javascript
js判断手机系统是android还是ios
Mar 07 Javascript
简单了解微信小程序 e.target与e.currentTarget的不同
Sep 27 Javascript
JavaScript Date对象功能与用法学习记录
Apr 28 Javascript
解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题
Jul 27 Javascript
修改Vue打包后的默认文件名操作
Aug 12 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编程过程中需要了解的this,self,parent的区别
2009/12/30 PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
2013/06/29 PHP
php 如何获取数组第一个值
2013/08/06 PHP
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
phpQuery让php处理html代码像jQuery一样方便
2015/01/06 PHP
详解WordPress中添加和执行动作的函数使用方法
2015/12/29 PHP
Zend Framework教程之Zend_Db_Table用法详解
2016/03/21 PHP
PHP基于MySQLI函数封装的数据库连接工具类【定义与用法】
2017/08/11 PHP
stripos函数知识点实例分享
2019/02/11 PHP
js中继承的几种用法总结(apply,call,prototype)
2013/12/26 Javascript
JS图片自动轮换效果实现思路附截图
2014/04/30 Javascript
JavaScript验证电子邮箱的函数
2014/08/22 Javascript
基于javascript实现的搜索时自动提示功能
2014/12/26 Javascript
Jquery 效果使用详解
2015/11/23 Javascript
Bootstrap风格的WPF样式
2016/12/07 Javascript
原生Javascript插件开发实践
2017/01/18 Javascript
详解nodejs中exports和module.exports的区别
2017/02/17 NodeJs
微信小程序提交form操作示例
2018/12/30 Javascript
Vue中的组件及路由使用实例代码详解
2019/05/22 Javascript
使用js在layui中实现上传图片压缩
2019/06/18 Javascript
给我一面国旗 python帮你实现
2019/09/30 Python
Django使用消息提示简单的弹出个对话框实例
2019/11/15 Python
python用quad、dblquad实现一维二维积分的实例详解
2019/11/20 Python
python实现梯度下降法
2020/03/24 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
win10安装python3.6的常见问题
2020/07/01 Python
Python利用myqr库创建自己的二维码
2020/11/24 Python
文秘自荐信
2013/10/20 职场文书
农林环境专业求职信
2014/03/13 职场文书
应届生求职自荐信
2014/07/04 职场文书
税务会计岗位职责
2015/04/02 职场文书
2015年保险公司工作总结
2015/04/24 职场文书
仙境之桥观后感
2015/06/16 职场文书
小学教师教学反思
2016/02/24 职场文书
小学语文的各类谚语(70首)
2019/08/15 职场文书
opencv 分类白天与夜景视频的方法
2021/06/05 Python