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 相关文章推荐
function foo的原型与prototype属性解惑
Nov 19 Javascript
潜说js对象和数组
May 25 Javascript
JQuery循环滚动图片代码
Dec 08 Javascript
jQuery的缓存机制浅析
Jun 07 Javascript
jQuery菜单插件superfish使用指南
Apr 21 Javascript
JavaScript对Cookie进行读写操作实例
Jul 25 Javascript
网页收藏夹显示ICO图标(代码少)
Aug 04 Javascript
javascript实现uploadify上传格式以及个数限制
Nov 23 Javascript
微信公众号 摇一摇周边功能开发
Dec 08 Javascript
ReactNative之键盘Keyboard的弹出与消失示例
Jul 11 Javascript
解决Vue编译时写在style中的路径问题
Sep 21 Javascript
React自定义hook的方法
Jun 25 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+ajax实现商品对比功能示例
2019/04/13 PHP
PHP面向对象程序设计子类扩展父类(子类重新载入父类)操作详解
2019/06/14 PHP
TP5框架请求响应参数实例分析
2019/10/17 PHP
javascript 尚未实现错误解决办法
2008/11/27 Javascript
js实现的复制兼容chrome和IE
2014/04/03 Javascript
微信小程序 location API接口详解及实例代码
2016/10/12 Javascript
详解ES6中的let命令
2020/04/05 Javascript
JavaScript Base64 作为文件上传的实例代码解析
2017/02/14 Javascript
Node.js通过身份证号验证年龄、出生日期与性别方法示例
2017/03/09 Javascript
NodeJS创建最简单的HTTP服务器
2017/05/15 NodeJs
JS高级技巧(简洁版)
2018/07/29 Javascript
Vue常用指令详解分析
2018/08/19 Javascript
Javascript 实现 Excel 导入生成图表功能
2018/10/22 Javascript
微信小程序顶部导航栏滑动tab效果
2019/01/28 Javascript
vue 二维码长按保存和复制内容操作
2020/09/22 Javascript
基于ajax实现上传图片代码示例解析
2020/12/03 Javascript
实例讲解python函数式编程
2014/06/09 Python
python数据结构之图深度优先和广度优先实例详解
2015/07/08 Python
Python随手笔记之标准类型内建函数
2015/12/02 Python
Python的Django框架中消息通知的计数器实现教程
2016/06/13 Python
Python分治法定义与应用实例详解
2017/07/28 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
Python使用requests提交HTTP表单的方法
2018/12/26 Python
详解python配置虚拟环境
2019/04/08 Python
详解Django定时任务模块设计与实践
2019/07/24 Python
python tkinter基本属性详解
2019/09/16 Python
利用Python实现字幕挂载(把字幕文件与视频合并)思路详解
2020/10/21 Python
Django-simple-captcha验证码包使用方法详解
2020/11/28 Python
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
美国最佳在线航班预订网站:LookupFare
2019/03/26 全球购物
教师绩效考核方案
2014/01/21 职场文书
幼儿园老师寄语
2014/04/03 职场文书
论文答谢词
2015/01/20 职场文书
学校禁毒宣传活动总结
2015/05/08 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书