`
cloudtech
  • 浏览: 4613898 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

避免闭包引发的问题

 
阅读更多

避免闭包引发的问题

闭包的功能强大,但如果没有正确理解闭包的概念,其结果往往出乎人的意料。例如,下面是一个较常见的问题:
<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 避免闭包引发的问题

    闭包的功能强大,但如果没有正确理解闭包的概念,其结果往往出乎人的意料。例如,下面是一个较常见的问题

    闭包问题html

    闭包文件

    离散数学-关系,集合,求自反闭包,对称闭包,传递闭包

    离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包...

    Java闭包 Java闭包

    JSR-335 将闭包引入了 Java 。闭包在现在的很多流行的语言中都存在,例如 C++、C# 。闭包允许我 们创建函数指针,并把它们作为参数传递。在这篇文章中,将粗略的看一遍Java8的特性,并介绍 Lambda表达式。而且将试...

    微信小程序闭包问题引发的JS闭包解决方案

    对于前端同学无论在面试还是在开发,都逃不过关于闭包的问题。最近小程序项目中遇到变量访问权限的问题一时间没考虑到闭包,郁闷了,在此感谢@Topqiang给我指点。本文阅读一遍不一定能够理解掌握,需要反复推敲和...

    数据库求属性集闭包&函数依赖闭包

    3) 计算属性集闭包的算法,在课件里有详细说明。方法很简单,但用文字描述很抽象。。。。不解释。。。 4) 计算函数依赖的闭包。此步骤不作要求,但要会方法。个人总结:将所有属性元素组成一个集合(域)记为R;...

    关系闭包的计算

    实验目的:熟悉warshall算法,掌握求关系的自反闭包,对称闭包和传递闭包的方法。 实验内容:从键盘输入一个关系的关系矩阵,自动求出自反闭包、对称闭包和传递闭包。 计算传递闭包用Warshall算法。 #include...

    内存泄露,闭包 内存泄露,闭包 内存泄露,闭包

    内存泄露,闭包 内存泄露,闭包 内存泄露,闭包

    C语言实现三种闭包算法(传递,自反,对称闭包)

    C语言实现三种闭包算法,能够实现传递,自反,对称闭包

    Swift之闭包ClosureDemo

    Swift之闭包ClosureDemo

    论文研究-求解最小闭包球问题改进的SMO-型算法.pdf

    研究[n]维空间中[m]个点的最小闭包球(MEB)问题。通过结合确定并删除内部点的技术到序列最小最优化(SMO)方法中,提出一种近似求解MEB问题的改进的SMO-型算法。证明了该算法具有线性收敛性。数值结果表明对于一些...

    Javascript 闭包完整解释

    Javascript 闭包完整解释

    C++对称闭包对称闭包

    用矩阵求对称闭包。简洁,轻松学习,相互交流。

    js闭包详细讲解

    js闭包的详细讲解

    计算NFA中ε闭包

    计算NFA中各个状态的闭包,从键盘上输入一个NFA的描述信息(输入格式自行定义),将 该NFA的描述信息保存到合适的数据结构中,然后计算出NFA中每个状态的ε_closure。

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...

    Python闭包实例closure.py

    Python闭包实例closure.py 简单示例闭包的使用 简单示例闭包的使用

    JS匿名函数、闭包

    但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止;使用闭包可以在JavaScript中模仿块级作用域(JavaScript本身没有块级作用域的概念),要点如下: 创建并立即调用一个函数...

    js闭包个人理解

    js闭包的个人理解

Global site tag (gtag.js) - Google Analytics