js闭包之我见
很久前的一个问题终于得以解决,内心是无比喜悦的,不多说,先上代码:
function test(){
for(var i=0;i<5;i++){
window.onclick=function(){
alert(i);
}
}
}
8 test()
原意是点击第一下弹出i的值0,点击第二下弹出i的值1,一直到第五次点击弹出4。想象是美好的,现实却不按常规出牌,无论点击多少次,alert出来的值都是5。后来接触了js闭包,才知道原来是它搞的鬼。看了不少相关书籍和博客后,发现其实它也没有想象得那么难。
我理解的闭包是可以访其他函数作用域的函数,在js中,通常通过在一个函数内部定义另一个函数来实现,如上例。提到闭包,应首先理解JavaScript特有的链式作用域,即一个函数作用域链的第一位是该函数本身的活动对象,第二位是包含该函数(即父函数)活动对象的索引,第三位是父函数的父函数活动对象的索引,以此类推,直至全局变量对象。注意,反之不成立,即父函数的作用域不包含子函数变量对象的索引。如图:
在文章开头的例子中,每个匿名函数(循环了五次,相当于五个匿名函数)的作用域链中都保存着test的活动对象,所以它们引用的是同一个变量i。当函数返回后,i的值是5,此时,每个函数都引用着保存变量i的对象,所以在每个函数内部,i的值都是5.
闭包具有两面性,有缺点,也有优点,在上例中因为对闭包使用不当没有达到想要的效果,但在一些特殊的应用中,只有用闭包才能实现相应的功能,接下来,就谈谈闭包的用途(优点)和注意事项(缺点)。
1、用途
- 从外部读取某个函数的局部变量。
子函数可以访问父函数的作用域,那么如果全局作用域需要访问函数的局部变量怎么办?
function myA(){
var a=6;
function myB(){
alert(a);
}
return myB;
}
var result=myA();
result();
在上述代码中,无法直接访问myA内的变量a,但是可以再内部定义一个函数myB,该函数可以访问它的父函数myA的作用域内的变量a,然后将这个函数返回并赋值给result,相当于在全局作用域内调用myB。
- 让某个局部变量始终保存在内存中
js的内存回收机制是这样的:当调用一个函数时,为它的局部变量对象分配相应的内存空间,一旦调用结束,则收回为它分配的内存。但是这样会有一个bug,即若在函数A内定义了函数B,而B也调用了A内的局部变量x,且B随时可能被全局调用,因为A调用完毕后内存被收回,所以B访问不到x。js的解决办法是,在定义一个函数时,把这个函数和它可能使用到的变量(包括自身变量和父函数的变量),统统一起保存起来,构成一个闭包,即便当父函数调用完毕,这些变量占用的内存也不会被收回。只有当该函数不可能被调用时,才会收回这些内存。
若需要随时访问某个局部变量,则可以通过该方法,构建一个闭包,让一个局部变量始终保存在内存中。
2、缺点
- 占用过多的内存
上述js的回收机制说明,只要闭包不被销毁,它的作用域链所占用的内存便不能被释放,若过多地、无用地占用内存,对效率和性能极为不利。
- 内存泄露
由于IE9之前的版本对JavaScript和COM对象使用不同的垃圾回收机制(因为IE9之前中的部分对象不是原生JavaScript对象,如其中的BOM和DOM就是以c++的COM对象实现的,所以回收机制不同),所以只要在IE9之前版本中涉及COM对象,就会导致循环引用,以至于对象内存不能被收回。具体来说就是,如果闭包的作用域中保存着一个HTML元素,则意味着该元素将无法被销毁,例如:
function f1(){
var e=document.getElementById("top");
element.onclick=function(){
alert(e.id);
};
}
上述代码为e元素事件创建了一个闭包,即匿名函数,由于匿名函数包含着对f1活动对象的引用,只要匿名函数存在,e元素的引用次数至少为1,因此它占用的内存便永远不会被收回(IE9对COM对象的垃圾回收机制决定的)。该问题也有相应的解决方法,请读者自行思考。
最后,关于闭包中this对象,需注意,由于匿名函数的作用域具有全局性,所以慎用闭包的this对象。没有用var声明的局部变量也具有全局性。
js闭包之我见的更多相关文章
- javascript作用域和闭包之我见
javascript作用域和闭包之我见 看了<你不知道的JavaScript(上卷)>的第一部分--作用域和闭包,感受颇深,遂写一篇读书笔记加深印象.路过的大牛欢迎指点,对这方面不懂的同学 ...
- js闭包的作用域以及闭包案列的介绍:
转载▼ 标签: it js闭包的作用域以及闭包案列的介绍: 首先我们根据前面的介绍来分析js闭包有什么作用,他会给我们编程带来什么好处? 闭包是为了更方便我们在处理js函数的时候会遇到以下的几 ...
- 大部分人都会做错的经典JS闭包面试题
由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) ...
- Js闭包常见三种用法
Js闭包特性源于内部函数可以将外部函数的活动对象保存在自己的作用域链上,所以使内部函数的可以将外部函数的活动对象占为己有,可以在外部函数销毁时依然存有外部函数内的活动对象内容,这样做的好处是可 ...
- js闭包之初步理解( JavaScript closure)
闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...
- (原创)JS闭包看代码理解
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- js闭包理解
js闭包的作用是使函数外可以访问函数内部的变量,是通过 在函数内部 定义 访问函数内变量 的函数实现的,内部的一个函数产生一个闭包 function a() { var i=0; return fun ...
- js闭包理解实例小结
Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 <script type="text/javascript"> ...
- Js闭包的用途
本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...
随机推荐
- Web前端工程师常去的15个技术网站
1.CSDN 网址:https://www.csdn.net/ 简介: CSDN (Chinese Software Developer Network) 创立于1999年,是中国最大的IT社区和服务 ...
- Ubuntu 网卡多个 IP 地址
临时添加 IP 地址 首先,让我们找到网卡的 IP 地址.在我的 Ubuntu 15.10 服务器版中,我只使用了一个网卡. 运行下面的命令找到 IP 地址: 复制代码 代码如下: sudo ip a ...
- 跨页传值c#
Application (4)URL地址中的参数 (5)通过隐藏字段来传递数据 (6)Server.Transfer (7)通过序列化对象 (8)........ 下面就分别一一介绍: (1)使用Se ...
- python的介绍和及基本的使用
一 什么是计算机 1 计算机就是由一堆硬件组成的一个机器. 2 硬件的分类: CPU:犹如人类的大脑,运行着需要运行的程序. 内存:将 CPU要运行的内容从硬盘中读取出来,然后CPU在内存里拿内容,只 ...
- 2018.09.27 bzoj2510: 弱题(概率dp+循环矩阵优化)
传送门 简单概率dp. 显然每次转移的式子可以用一个矩阵表示出来: 这个是循环矩阵. 因此只用维护第一行快速幂一波就行了. 代码: #include<bits/stdc++.h> #def ...
- Python 插件(add-in)基础知识
1) Python插件为何物 一个插件(add-in)就是一个客户化,比如嵌入到ArcGIS应用程序中的工具条上的一系列工具,这些工具作为ArcGIS标准程序的补充可以为客户完成特殊任务. ArcG ...
- MEF程序设计指南
############################################################################################## ##### ...
- HDU2577 How to Type 2016-09-11 14:05 29人阅读 评论(0) 收藏
How to Type Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- Linux C 创建目录函数mkdir相关【转】
转自:http://blog.csdn.net/fallenink/article/details/8480483 原文地址:http://sharp2wing.iteye.com/blog/1280 ...
- hdu1302 The Snail
题目 题目大意: 一只蜗牛在H英尺高的底部,想爬到顶端.蜗牛可以在太阳升起的时候爬上U英尺,但是在晚上睡觉的时候会滑下D英尺.蜗牛的疲劳系数为F(百分比), ...