js闭包的理解

闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点:
  1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
  简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

《高级程序设计》上,这样说:当在函数内部定义了其他函数时候,就创建了闭包。闭包有权访问包含函数内部的所有变量。

这句话怎么理解呢?照这句话理解的话,闭包就是一个嵌套函数嘛!嵌套函数对包含它的函数的变量当然可以访问,这是没有问题的。

近似正确的短答案:闭包就是一个函数把外部的那些不属于自己的对象也包含(闭合)进来了。

短答案:JavaScript中的闭包,无非就是变量解析的过程

首先看一段话:
每次定义一个函数,都会产生一个作用域链(scope chain)。当JavaScript寻找变量varible时(这个过程称为变量解析),总会优先在当前作用域链的第一个对象中查找属性varible ,如果找到,则直接使用这个属性;否则,继续查找下一个对象的是否存在这个属性;这个过程会持续直至找到这个属性或者最终未找到引发错误为止

JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。

一般来说,内部函数是能够访问到上一级乃至全局的的变量的,那么就有人这样理解:通过闭包,可以实现外部访问函数局部内的变量。

(如果我们把作用域简单的分个级的话,假设全局作用域作为第一级,其中定义的函数体内部作用域作为第二级,在第二级作用域内嵌套定义的函数体内部作用域作为第三级,....等等,传统意义上,第一级不能访问第二级的变量(这种变量叫做局部变量),第二级不能访问第三级,...,而反过来是可以的,这就是作用域链。本级作用域内找不到再到上一级找,直至第一级全局。而闭包这种机制可以在第一级作用域中通过第三级作用域引用到第二级作用域中的变量,而方法就是在第二级作用域向第一级作用域返回拥有第三级作用域的函数引用。 这个引用才是关键,因为这个引用的存在,相关的第三作用域与第二作用域都成了这个引用运行的上下文,迫使垃圾回收机制GC不能回收这条链上所占用的资源。而如果没有这个引用,则跟一般函数一样,函数运行完资源就会被回收。而我的疑惑也在于此,闭包单指函数中的嵌套函数还是指被第一级引用了的嵌套函数?还是都是?还是说闭包并不是嵌套函数而是嵌套函数被第一级作用域引用时所形成的这种机制?)

function a(){
        var n = 999;
        function b(){
            alert(++n);
        }
        return b();
    }
    var c = a();

即,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。

由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。

那么,如果a不返回函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。

实际上是就是闭包延长变量的生命周期。通常函数的作用域即变量会在函数执行结束后被销毁,但当函数返回一个闭包,只要闭包不被释放,整条作用域链都会占用内存。(闭包延长变量的生命周期,这是指被第一级引用的情况。但如果没有这个引用,闭包还能称其为闭包吗?

说道作用域链:即 函数自己的作用域、上一层的函数的作用域....和全局作用域。访问一个变量时,自己的没有,就一层层往上找,直至全局,若还没有,就报错。

PS: 有网友推荐了另一篇文章javascript闭包概念简单解析,是不是权威暂且不提,总算有一个明确的概念:

说了这么多,闭包到底是什么,下面做一下总结:

闭包是一个概念,它描述了函数执行完毕内存释放后,依然内存驻留的一个现象,只要把握这个核心概念,闭包就不难理解了。

猜你喜欢

转载自blog.csdn.net/yangymy/article/details/79093175