浅谈对闭包(Closure)的理解

在理解闭包前理解JavaScript的作用域是有必要的,如果有兴趣,请移步"对JavaScript作用域的认识"

什么是闭包

闭包就是指有权访问另一个函数作用域中变量的函数,通俗点讲闭包就是能够读取其他函数变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。

 1         function fn1() {
 2             var a = 1 ;
 3             function fn2() {
 4                 alert(a);
 5             }
 6             return fn2;
 7         }
 8
 9         var result = fn1();
10         result();  //1

上述函数fn2就是一个闭包,我们可以通过返回fn2获取到fn1中的变量。

闭包的用途

第一个用途就是上述通过闭包去访问函数内部的变量,第二个常见的用途就是使某些变量常驻内存

 1         //没有闭包情况下变量a的情况
 2         function add() {
 3             var a = 1;
 4             a++;
 5             alert(a);
 6         }
 7         add();   //2
 8         add();   //2
 9
10         //有闭包的方式下
11         function add2() {
12             var a = 1;
13             function fn() {
14                 a++;
15                 alert(a);
16             }
17             return fn;
18         }
19         var result = add2();
20         result();  //2
21         result();  //3

在有闭包的情况下,result()的两次输出分别是2,3,这说明aad2中的a变量一直在内存当中,并没有因为add2的调用后被垃圾回收机制回收(garbage collection)。

为什么会产生这样的情况?这是因为add2是fn的父亲函数,而在全局环境当中,fn其实是被赋给了全局变量result的,而result只会在全局环境执行完所有代码之后才会被回收,所以就导致了fn常驻内存,而fn的存在又依赖于父亲函数add2,所以add2在被调用之后也不会别GC回收,也始终存在于内存当中。

闭包可能会引发的问题

由于IE9之前的版本对JSript对象和COM对象使用了不同的垃圾回收机制,所以闭包在IE9之前的版本中会导致内存泄漏问题。具体来说就是,如果闭包中保存着一个HTML元素,那么这个元素将无法被销毁,直到退出程序或关闭浏览器。

1     <script>
2         window.onload = function () {
3             var oBox = document.getElementById(‘box‘);
4
5             oBox.onclick = function () {
6                 alert(oBox.id);
7             }
8         };
9     </script>

像上述的情况下就发生了内存泄漏,因为在闭包中创建了一个循环引用。可以通过以下方法得到解决

 1     <script>
 2         window.onload = function () {
 3             var oBox = document.getElementById(‘box‘);
 4
 5             oBox.onclick = function () {
 6                 alert(oBox.id);
 7             };
 8
 9             //方法一
10             window.onunload = function () {
11                 oBox.onclick = null;
12             }
13         };
14
15         //方法二
16         window.onload = function () {
17             var oBox = document.getElementById(‘box‘);
18             var id = oBox.id;
19
20             oBox.onclick = function () {
21                 alert(id);
22             };
23
24             oBox = null;
25         };
26
27     </script>
时间: 2024-12-14 18:05:05

浅谈对闭包(Closure)的理解的相关文章

【转载】李航博士的《浅谈我对机器学习的理解》 机器学习与自然语言处理

李航博士的<浅谈我对机器学习的理解> 机器学习与自然语言处理 [日期:2015-01-14] 来源:新浪长微博  作者: 李航 [字体:大 中 小] 算算时间,从开始到现在,做机器学习算法也将近八个月了.虽然还没有达到融会贯通的地步,但至少在熟悉了算法的流程后,我在算法的选择和创造能力上有了不小的提升.实话说,机器学习很难,非常难,要做到完全了解算法的流程.特点.实现方法,并在正确的数据面前选择正确的方法再进行优化得到最优效果,我觉得没有个八年十年的刻苦钻研是不可能的事情.其实整个人工智能范畴

浅谈元类(个人理解)

浅谈元类(个人理解) 我们知道在python中一切皆对象(object),那么所以有的对象都成了object的子类,那么object类又是由谁创建的呢? 实际上,能够创建类的类,叫元类.还有一个概念就是:元类创建了object类,同时又是object类的子类(这是什么鬼?我们就不去考虑这个逻辑了,已经完美解决了先有鸡还是先有蛋的问题了). 元类实际还是所有类的创建者,即使所有类(包括元类自己)都是object的子类,他们的关系如下: Interesting...... 原文地址:https://

浅谈JavaScript闭包

一.背景知识 在介绍闭包之前,我觉得有必要先简单的介绍一些背景知识,如变量的作用域.嵌套函数.垃圾回收机制等概念. 1.作用域 作用域是程序运行时变量可被访问的范围,定义在函数内的的变量是局部变量,局部变量的作用域只能是函数内部范围内,它不能在函数外引用.定义在模块最外层的的变量是全局变量,它是全局范围内可见的,当然在函数里面也可以读取到全局变量的. var a = 123; //全局变量 function fun(){ var b = 456; //局部变量 } 2.嵌套函数 函数不仅可以定义

10 浅谈 装饰器模式的理解与使用

在不改变现有类结构的情况下,为这个类添加一个新的功能,这就是装饰器模式 所属与结构型模式, 这种模式的特点是:需要创建一个装饰类来包装原有的类,并且提供额外的功能. 为了解决:平时使用继承的方式,会带入许多静态的方法,导致子类过度饱和,膨胀. 举例子:悟空拥有七十二变,不管它怎么变化,他的本质还是一只猴子,但是他又有变化后的一些本领(功能) 实现:装饰类包含原有类的实例对象,即可实现装饰器模式 开始: 定义一个形状的接口 //画图接口 public interface Shape { void

浅谈对差分隐私的理解

在听完第五组的报告之后,浅谈一下对差分隐私的认识,主要针对差分隐私的思想做一个大致的梳理. 为什么会产生差分隐私? 由于有些“聪明”的用户为了知道某些信息,可以通过两次查询结果的差异进行对比,从而在两次数据的对比中找到有用的信息.正如在杨顼组的报告中提到的查询二等兵约瑟夫阿伦是否阵亡的信息,可以通过查询D5和D6两次数据结果,将两次数据结果进行对比就可以知道约瑟夫阿伦是否阵亡的消息. 差分隐私的主要思想: 差分隐私是基于噪音的安全计算方法,它的思想是:对计算过程用噪音干扰,让原始数据淹没在噪音中

js闭包(closure),个人理解

一.闭包概念理解 各种专业文献上对js"闭包"(closure)定义非常抽象,贼难看懂.我的理解是,闭包就是能够读取某函数内部变量的函数.由于在Javascript语言中只有在函数内部的函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数".所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁. 二.用途 闭包可以用在很多地方.但它最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中. 三.使

浅谈JavaScript闭包、this指针、作用域(一)

认识闭包: 闭包,是指有权限访问到其他函数作用域的变量的函数 给一个例子: function outer () { var name = 'HelloTF'; return function () { console.log (name); } } var getName = outer(); getName(); //HelloTF 函数outer执行后返回一个内部的匿名函数,并把返回的结果赋值给全局变量result,在全局环境中在此执行result,得到了outer函数内部的变量name.

浅谈JS闭包中的循环绑定处理程序

初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript的闭包特性. 前几天工作中写前端js代码时,遇到了遍历元素给它添加单击事件. (PS:之前也在<jQuery基础教程>第四版中看过讲循环绑定处理程序的内容,当时估计也没怎么用心看,所以没记起来.) 大神要是知道这类情况,可以关掉窗口,写这些主要是给像我一样的小白看的,谢谢! 先贴上错误的例子让大家

浅谈JS闭包和this关键字

问题背景:由于JS中闭包的存在和this的特殊性使得很多时候无法判断出变量的值. 一.闭包中的变量 例1. var name="The Window"; var getName=(function(){         var name = "My function";         return function(){             return name;         }     })();   console.log(getName());//