对于闭包的理解

什么是闭包?

闭包指的是:能够访问另一个函数作用域的变量的函数。简单来说就是:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量;也可以说它是一种在JS编程中解决问题的办法,是一种特殊结构:重复使用变量又不让变量被污染的机制。这个概念看着感觉是蛮简单,但是实际真正的去理解又感觉很麻烦。

我们都知道在JS中所有变量都是通过内存中的栈和堆来存放的,基本数据类型一般都是放在栈里,而引用性数据类型则是需要存放在堆里然后再通过对应的空间地址来进行引用,我们现在就要通过分析数据在堆栈中的引用存储来解析程序在执行过程中的具体情况。

在理解闭包这种机制之前我们需要对程序的执行步骤有一定的了解,一个是程序的执行前的预编译,以及作用域和作用域链,在这里我就不再多做解释,在之前的博客中有写过关于预编译&作用域链的相关知识;
这里我们可以用一个demo来分析理解:

function outer(){
	var num = 100;
	function enter(){
		document.write(num);
	}
	return enter;
}
var getenter = outer();
getenter();

上面这段代码是一个简单的闭包案例:
首先我们现在先来从整个代码块上分析,outer()这个函数现在是处在Window底下(全局作用域),那么它如果要执行;

在执行前(所谓的预编译):它会在Window这个全局作用域中创建一个GO{ }对象,此时GO{ outer:function, getenter:undefined};而outer( )此时也会创建它自己的活动对象AO{ },此时AO{ num:undefined,enter:function};而enter( )中并没有变量以及函数,所AO{ }中为空。

此时开始执行函数outer它的AO{num:100,enter:function}。而函数outer( )中的函数enter( )因为没有调用所以不执行,接着往下执行,"return enter;"将enter( )这个函数返回出去,此时enter( )中的打印num的语句并没有执行;接着向下看,此时GO{getenter:outer()},outer( )这个函数被作为一个变量值并且是执行后赋给getenter,那么此时getenter的值就是outer( )执行后返回的值,也就是outer( )函数内return返回的enter( )函数代码块,然后接着执行最后一句代码:“getenter( )”,本身它是一个变量,但是outer( )把返回的enter( )代码块赋值给它之后,它也就成为了一个可以执行的函数,当它执行时也就相当于时enter( )执行了,这时需要打印的num就会开始寻找它所匹配的值,因为在enter( )中没有找到,所以它就向上一级进行访问,这时在outer( )中的AO中访问到,于是便获得num的值输出打印;

注意: 因为在栈里面数据的出让顺序是先进的后出,所以当函数开始执行时它会从它自身的AO中先去访问变量,如果没有就会向上一层去进行访问直到找到并赋值,找不到的话则程序抛出undefined的错误。

闭包的作用:

优点:

  1. 不会造成全局变量的污染;
  2. 可以在函数的外部访问到函数内部的局部变量(实现所谓的变量‘公有化’)。
  3. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。

缺点:

  1. 闭包导致作用域链的不释放,会造成内存溢出,所以就会占用内存空间
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值