菜鸟所理解的闭包

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了菜鸟所理解的闭包相关的知识,希望对你有一定的参考价值。

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

>>进入主题

  什么是闭包:闭包是指有权访问另一个函数作用域的变量的函数。--《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(); // outer
globalVar(); // inner;

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

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

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

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

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

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

 

以上是关于菜鸟所理解的闭包的主要内容,如果未能解决你的问题,请参考以下文章

深入理解JavaScript——闭包

JS---闭包

我所理解的JavaScript闭包

JavaScript--我所理解的闭包

重新理解闭包

Javascript关于闭包的个人理解