简析JavaScript中的Closure(闭包)

        闭包是什么?官方对闭包的解释是这样的:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包其实并不难理解,然而,通过阅读有关它的文献,我们是不可能理解闭包这个概念的。(其实理解闭包前,应该先了解js中的作用域)下面通过具体例子来理解闭包。

1.下述代码中就有一个闭包,因为匿名函数function( ) { alert(text);}在另一个函数中声明为f( )。在JavaScript中,如果在另外一个函数中使用function关键字,那么就会创建一个闭包。作为对比,在C语言中,函数返回后,所有的局部变量都不能访问,因为堆栈帧被破坏了。而在javascript中,如果在一个函数中声明另一个函数,那么在从调用的函数返回后,父函数中的局部变量可以继续被访问。例如在这个例子中,我们在sayHi()中返回了函数say(),并把它赋值给了f,而恰好say()中使用了局部变量text,所以我们能在sayHi()函数运行结束后,继续使用sayHi()中的变量text。原因呢?这是javacript中特有的“链式作用域”结构导致的,子对象会一级一级向上寻找所有父对象的变量,换句话说,父对象所有的变量对于子对象是可见的;我们想要在sayHi()外部访问它内部的变量,我们就可以通过返回它内部一个函数,从而在外部读取它的内部变量。举个例子说明,隔壁老王想了解我的信息,于是养了一只狗,而我喜欢这只狗,于是我挖了一个狗洞给它,然后这只狗通过这狗洞进了我的家,把我所有的信息都采集到了,然后带给了隔壁老王,那么这只狗就是闭包狗。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。闭包好烦啊,为什么不用全局变量呢?你boss可能会炒了你。

简析JavaScript中的Closure(闭包)_第1张图片

2.闭包一个作用是让外部读取函数内部的变量,另一个就是让这些变量始终保存在内存中。话不多说,请看下面的例子:result就是闭包f2()函数,它一共运行了两次,第一次值为999,第二次为1000.我们就可以知道,函数f1()中的变量n一直保存在内存中,并没有在f1()调用后被自动清除。原因呢?因为函数f2(),函数f2()被赋给了一个全局变量result,这导致函数f2()一直存在于内存中,而f2()活在f1()中,所以f1()也将一直在内存中,并不会在调用结束后被回收。nAdd的值同样也是一个闭包(因为它是一个匿名函数),并且nAdd是一个全局变量,所以此时的nAdd相当于是一个setter,所以可以在函数的外部对函数内部的局部变量n进行操作。

简析JavaScript中的Closure(闭包)_第2张图片

3.闭包不能滥用,因为闭包会使得函数中的变量都保存在内存中,内存消耗很大,否则会引发一系列的性能问题。怎么解决呢?在退出函数之前,把不用的局部变量全部毁掉。闭包可以在父函数外部改变父函数内部的变量,如果把父函数当作对象使用,那怎么办呢?233333

4.如果能理解下面这个例子,那么闭包应该能理解一半了。(上一个stack overflow上大神的example)


简析JavaScript中的Closure(闭包)_第3张图片

你可能感兴趣的:(简析JavaScript中的Closure(闭包))