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对象和DOM对象的相互转化实现代码
Mar 02 Javascript
ExtJs Excel导出并下载IIS服务器端遇到的问题
Sep 16 Javascript
基于JQuery和CSS3实现仿Apple TV海报背景视觉差特效源码分享
Sep 21 Javascript
JS图片定时翻滚效果实现方法
Jun 21 Javascript
node.js实现博客小爬虫的实例代码
Oct 08 Javascript
JavaScript之RegExp_动力节点Java学院整理
Jun 29 Javascript
layui框架中layer父子页面交互的方法分析
Nov 15 Javascript
echarts设置图例颜色和地图底色的方法实例
Aug 01 Javascript
jquery实现选项卡切换代码实例
May 14 jQuery
手把手带你入门微信小程序新框架Kbone的使用
Feb 25 Javascript
react 不用插件实现数字滚动的效果示例
Apr 14 Javascript
Node.js中的异步生成器与异步迭代详解
Jan 31 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获取数组最后一个值的2种方法
2015/01/21 PHP
PHP面向对象学习之parent::关键字
2017/01/18 PHP
Js 获取HTML DOM节点元素的方法小结
2009/04/24 Javascript
JavaScript中valueOf函数与toString方法深入理解
2012/12/02 Javascript
JQuery页面图片切换和新闻列表滚动效果的具体实现
2013/09/26 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/20 Javascript
jquery教程限制文本框只能输入数字和小数点示例分享
2014/01/13 Javascript
jQuery动画效果animate和scrollTop结合使用实例
2014/04/02 Javascript
jquery map方法使用示例
2014/04/23 Javascript
jquery操作checked属性以及disabled属性的多种方法
2014/06/20 Javascript
js style动态设置table高度
2014/10/21 Javascript
Jquery 分页插件之Jquery Pagination
2015/08/25 Javascript
浅析javascript的return语句
2015/12/15 Javascript
微信小程序 详解Page中data数据操作和函数调用
2017/01/12 Javascript
php 解压zip压缩包内容到指定目录的实例
2018/01/23 Javascript
详解Require.js与Sea.js的区别
2018/08/05 Javascript
从0到1构建vueSSR项目之node以及vue-cli3的配置
2019/03/07 Javascript
优雅地使用loading(推荐)
2019/04/20 Javascript
cordova+vue+webapp使用html5获取地理位置的方法
2019/07/06 Javascript
在Django的上下文中设置变量的方法
2015/07/20 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
Django model序列化为json的方法示例
2018/10/16 Python
Python通过paramiko远程下载Linux服务器上的文件实例
2018/12/27 Python
在Python中通过getattr获取对象引用的方法
2019/01/21 Python
简单了解python中对象的取反运算符
2019/07/01 Python
Python通过递归获取目录下指定文件代码实例
2019/11/07 Python
浅析CSS3 中的 transition,transform,translate之间区别和作用
2020/03/26 HTML / CSS
Html5 postMessage实现跨域消息传递
2016/03/11 HTML / CSS
Piercing Pagoda官网:耳环、戒指、项链、手链等
2020/09/28 全球购物
物流管理专业应届生求职信
2013/11/21 职场文书
项目专员岗位职责
2013/12/04 职场文书
机械个人求职信范文
2014/01/24 职场文书
推广普通话演讲稿
2014/05/23 职场文书
村当支部个人对照检查材料思想汇报
2014/10/06 职场文书
婚礼父母答谢词
2015/01/04 职场文书
工作时间证明
2015/06/15 职场文书