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 arguments 传递给函数的隐含参数
Aug 21 Javascript
javascript setAttribute, getAttribute 在不同浏览器上的不同表现
Aug 05 Javascript
用Mootools获得操作索引的两种方法分享
Dec 12 Javascript
js之事件冒泡和事件捕获详细介绍
Oct 28 Javascript
javascript上下方向键控制表格行选中并高亮显示的方法
Feb 13 Javascript
javascript实现日期按月份加减
May 15 Javascript
如何实现移动端浏览器不显示 pc 端的广告
Oct 15 Javascript
javascript中return,return true,return false三者的用法及区别
Nov 17 Javascript
轻松学习Javascript闭包
Mar 01 Javascript
Bootstrap模态框插入视频的实现代码
Jun 25 Javascript
详解webpack-dev-server 设置反向代理解决跨域问题
Apr 18 Javascript
vue实现下拉菜单树
Oct 22 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
日本十大科幻动漫 宇宙骑士垫底,第一已成经典
2020/03/04 日漫
PHP 文本文章分页代码 按标记或长度(不涉及数据库)
2012/06/07 PHP
非常好用的Zend Framework分页类
2014/06/25 PHP
php 生成签名及验证签名详解
2016/10/26 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
php解析非标准json、非规范json的方式实例
2020/12/10 PHP
javascript Base类 包含基本的方法
2009/07/22 Javascript
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
Google排名中的10个最著名的 JavaScript库
2010/04/27 Javascript
Extjs中DisplayField的日期或者数字格式化扩展
2010/09/03 Javascript
JavaScript中的几个关键概念的理解-原型链的构建
2011/05/12 Javascript
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
jquery map方法使用示例
2014/04/23 Javascript
jQuery Validate插件实现表单强大的验证功能
2015/12/18 Javascript
很不错的两款Bootstrap Icon图标选择组件
2016/01/28 Javascript
jquery中键盘事件小结
2016/02/24 Javascript
基于jquery实现表格内容筛选功能实例解析
2016/05/09 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
基于JavaScript实现验证码功能
2017/04/01 Javascript
浅谈react.js中实现tab吸顶效果的问题
2017/09/06 Javascript
shiro授权的实现原理
2017/09/21 Javascript
使用Angular 6创建各种动画效果的方法
2018/10/10 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
cordova+vue+webapp使用html5获取地理位置的方法
2019/07/06 Javascript
Vue  webpack 项目自动打包压缩成zip文件的方法
2019/07/24 Javascript
精确查找PHP WEBSHELL木马的方法(1)
2011/04/12 Python
python基础教程之自定义函数介绍
2014/08/29 Python
在Python中使用正则表达式的方法
2015/08/13 Python
Python中的 is 和 == 以及字符串驻留机制详解
2019/06/28 Python
关于pytorch中全连接神经网络搭建两种模式详解
2020/01/14 Python
数学高效课堂实施方案
2014/03/29 职场文书
艺人经纪人岗位职责
2014/04/15 职场文书
技术负责人任命书
2014/06/05 职场文书
学子宴致辞大全
2015/07/27 职场文书
幼儿园小班班务总结
2015/08/03 职场文书
python生成可执行exe控制Microsip自动填写号码并拨打功能
2021/06/21 Python