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

Javascript
JavaScript 拖拽实现(附注释),最经典简单短小精悍!
学习drag and drop js实现代码经典之作
jquery创建div 实现代码
jquery遍历input取得input的name
jQuery 对象中的类数组操作
js 发个判断字符串是否为符合标准的函数
细品javascript 寻址,闭包,对象模型和相关问题
在IE上直接编辑网页内容的js代码(IE地址栏js)
一个选择最快的服务器转向代码
JQUERY 对象与DOM对象之转换
javascript 对象比较实现代码
jquery 获取json数据实现代码
Firefox div高度自适应
xml和web特殊字符
js 表单验证方法(实用)
ie和firefox不兼容的解决方法集合
js 数组操作代码集锦
js checkbox(复选框) 使用集锦
JS 判断代码全收集
理解JavaScript的caller,callee,call,apply

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 166 ::
收藏到网摘: 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之间的相互作用域链上下文环境的关系。如果运用得当,嵌套的内部函数所拥有的潜能将超出了我们的想象力。