Js闭包的原理(图解)

JavaScript038

Js闭包的原理(图解),第1张

什么是闭包(Closure)?

网上流传各种说法,在Javascript语言中,我的理解是: 保存着其他函数内部变量的函数,就是闭包。

挺绕的,但不虚,让我们一步步揭开它的神秘面纱!

要理解闭包,我们得先搞清楚以下几个概念:

JS的作用域分两种:全局作用域、局部作用域(也可称为函数作用域)

总的来说,Js作用域的一般机制就是:内部可访问外部的变量,外部无法访问内部的变量。

那么这套作用域机制是如何实现的呢?答案是:通过作用域链

在Js中,每当一个函数被执行,都会产生三个对象:

我们通过实例配图讲解,例如有如下 js 文件:

当浏览器运行解析 example.js 后,首先创建了全局执行环境 (Window 对象)、Window 作用域链和 Global 全局活动对象,如图:

搞明白了作用域链,离弄清楚什么是闭包就仅一步之遥了! 我们来看看下面这个实例:

当执行 var func = outer() 时,情况如图:

接下来,当执行 console.log(func()) 时, 情况如图:

这种情况不是闭包吧,最近刚开始看。

function a(){

var i=0

function b(){

alert(++i)

}

return b

}

c= a()

c()

c()

类似这种才叫闭包吧。

你这种变量不在函数体内的,不能形成闭包的吧(个人理解)。

楼主当然可以直接在函数内修改a的值,并且能成功,但是这并不是闭包的效果,因为你的a本来就在函数之外的一个变量,其他任何函数都可以调用或者修改他。

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

 闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样.

但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的理解以及js内部解释器的运作方式的描述,都是可以看出你js实际水平的.即使你没答对,也能让考官对你的水平有个评估.那么我先来说说我对js中的闭包的理解.

闭包是很多语言都具备的特性,在js中,闭包主要涉及到js的几个其他的特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等.

在理解闭包以前.最好能先理解一下作用域链的含义,简单来说,作用域链就是函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在最前面,把自身的父级函数中的变量放在其次,把再高一级函数中的变量放在更后面,以此类推直至全局对象为止.当函数中需要查询一个变量的值的时候,js解释器会去作用域链去查找,从最前面的本地变量中先找,如果没有找到对应的变量,则到下一级的链上找,一旦找到了变量,则不再继续.如果找到最后也没找到需要的变量,则解释器返回undefined.

了解了作用域链,我们再来看看js的内存回收机制,一般来说,一个函数在执行开始的时候,会给其中定义的变量划分内存空间保存,以备后面的语句所用,等到函数执行完毕返回了,这些变量就被认为是无用的了.对应的内存空间也就被回收了.下次再执行此函数的时候,所有的变量又回到最初的状态,重新赋值使用.但是如果这个函数内部又嵌套了另一个函数,而这个函数是有可能在外部被调用到的.并且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题.如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要的外部函数中变量的值了.所以js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一起保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收.