当前位置: 首页 > 图文教程 > 网络编程 > Javascript > javascript 避免闭包引发的问题

Javascript
JS 文件本身编码转换 图文教程
jQuery Ajax之$.get()方法和$.post()方法
jQuery Ajax之load()方法
JavaScript 核心参考教程 内置对象
JavaScript 核心参考教程 RegExp对象
javascript hashtable实现代码
百度留言本js 大家可以参考下
javascript 判断某年某月有多少天的实现代码 推荐
让iframe子窗体取父窗体地址栏参数(querystring)
jquery pagination插件实现无刷新分页代码
jQuery与javascript对照学习 获取父子前后元素 实现代码
通用javascript脚本函数库 方便开发
JQuery 绑定事件时传递参数的实现方法
支持IE,Firefox的javascript 日历控件
javascript 变速加数功能实现代码
extjs 学习笔记(一) 一些基础知识
extjs 学习笔记(二) Ext.Element类
Jquery 学习笔记(一)
一些技巧性实用js代码小结
jquery 常用操作整理 基础入门篇

Javascript 中的 javascript 避免闭包引发的问题


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 196 ::
收藏到网摘: n/a

闭包的功能强大,但如果没有正确理解闭包的概念,其结果往往出乎人的意料。例如,下面是一个较常见的问题 <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之间的相互作用域链上下文环境的关系。如果运用得当,嵌套的内部函数所拥有的潜能将超出了我们的想象力。