首页 > 代码库 > 菜鸟所理解的闭包

菜鸟所理解的闭包

  对于新手来说,闭包的概念往往有些晦涩。书上的概念描写的非常简短,网上的各类文章又常常是长篇大论地探讨闭包的作用呀,影响呀,看到最后,觉得是越看越晕,越来越搞不懂什么是闭包了,所以在这里分享自己对闭包的浅显的理解,希望对新手有所帮助,相互交流。

>>进入主题

  什么是闭包:闭包是指有权访问另一个函数作用域的变量的函数。--《javascript高级程序设计》

  书上的概念就这么一句话,其实闭包就是像这句话定义的一样简单。如果有一个函数fun2,它可以访问在其它函数如fun1中的局部变量,那么它(fun2)就是闭包。创建闭包的简单方式,就在在函数内部创建另一个函数,下面例子创建了个简单的闭包

1 function fun1 () {2     var  a = 0;3     function fun2 () { 4         console.log(a); // 在这个函数fun2中可以访问另一个函数中的变量a,所以fun2()就是一个闭包。5     }6     fun2();7 }

  上面这个闭包运行其实和大家所熟悉的函数运行没什么两样,也不会出现各种关于闭包的问题,正常地访问外部函数的变量,数据。以上就是闭包的定义,非常简单,我们不用把它想得过于复杂。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~定义分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  那么问题来了,为什么闭包那么重要呢,不是说好的有各种注意事项的么。是的,我们通常可以像上面那样直接在外部函数内调用函数,即直接调用闭包。但是有时候会出现其他的调用情形,在其他地方调用内部函数(闭包),使这个闭包逃离定义它们的外部函数。

  所以接下来我们简单讨论闭包如何在其他地方被调用(逃离),以及会产生怎样的影响(基于闭包在其他地方被调用的情形,并不是所有闭包都会出现这种影响)

  逃离方式:

    1.将内部函数指定给一个全局变量;

var globalVar;function outer() {    console.log(‘outer‘);    function inner(){        console.log(‘inner‘);    }    globalVar = inner;      }outer(); // outerglobalVar(); // inner;

在这个例子中inner()通过全局变量的引用成功逃离,现在可以在全局中调用,而且可以引用outer()的变量

    2.通过返回值来‘营救‘内部函数的引用

function outer() {    console.log(‘outer‘);    function inner(){        console.log(‘inner‘);    }   return inner;      }var fn = outer(); // outerfn(); // inner;

在这个例子中inner()通过返回值成功逃离,现在可以在全局中调用,而且可以引用outer()的变量

  上面两个例子中对内存的影响:

    本来正常的情况下是函数调用结束之后函数的执行环境离开环境栈,定义的变量废弃(废弃与垃圾收集机制有关),活动变量(变量对象)会被销毁,内存释放。但是现在因为闭包的作用域链包含了外部函数的变量对象,外部函数的变量有可能再被引用,垃圾收集机制不会将外部函数的变量废弃,在内存保留的外部函数的变量对象。这样就加大了对内存的占用。

 

菜鸟所理解的闭包