本篇文章我们来学习和讨论一下js中的闭包。闭包是纯函数式编程的一个特性,因为它们能够大大简化复杂的操作。在js中,闭包的重要性不言而喻!

简单的说,闭包(closure)是 一个函数在创建时 允许 该自身函数 访问并操作 该自身函数之外的变量时 所创建的作用域。换句话说,闭包可以让函数访问所有的变量和函数,只要这些变量和函数存在于该函数声明时的作用域内就行。要记住,声明的函数在后续什么时候都可以被调用,即便声明时的作用域消失之后。我们通过下面一小段代码来开始本次学习:

var outerValue="outer";
function outerFunction(){
    //调用函数外部变量outerValue
    alert(outerValue);
}
//执行outerFunction函数
outerFunction();

我们在同一个作用域内声明一个变量outerValue和函数outerFunction(),可以看见,outerFunction()函数能够访问并操作outerValue变量,这样的代码,我们已经写了无数次,但是却没有意识到其实这正在创建一个闭包。这并不奇怪,因为变量outerValue和函数outerFunction()都是在全局作用域内声明的,该作用域(实际上就是一个闭包)从未消失过(因为页面已经被加载了),不足为奇,该函数outerFunction()可以访问到外部变量outerValue,因为它仍在作用域内并且是可用的。只不过,在这种情况下,即便闭包存在,也不清楚它的好处。

接下来,我们再次演变一下代码:

var outerValue="outer";
var later;

function outerFunction(){
    var innerValue="inner";
    
    function innerFunction(){
        //调用外部函数的innerValue变量
        alert(innerValue); 
        
        //调用外部函数的afterValue变量
        alert(afterValue);         
    }
    var afterValue="after";
    
    //将innerFunction函数引用到later
    later=innerFunction;
}
//执行outerFunction函数
outerFunction();
//执行innerFunction函数
later();

//inner
//after

当outerFunction()函数执行之后,outerFunction()函数的作用域已经消失了。按照函数的作用域来说,通常,此时的innerValue和afterValue变量已不存在了。但是上面的代码真的是这样执行的吗?当然不是!在outerFunction()函数执行之后,我们将内部函数innerFunction的引用赋值给全局变量later来进行调用。此时,later变量引用的innerFunction函数是可用调用到innerValue和afterValue变量的。为什么?因为闭包!

在外部函数outerFunction中声明内部函数innerFunction的时候,不仅仅是声明了innerFunction函数,还创建了一个闭包,该闭包不仅包含函数声明,还包含了内部函数innerFunction声明的那一时刻点上,外部函数作用域中的所有变量。最终当innierFunction函数执行的时候,外部函数outerFunction的作用域已经消失了,通过闭包,innerFunction函数还是可以访问到原始作用域的。

通过以上代码可以看出:

1、内部函数的参数是包含在闭包中的;

2、内部函数作用域之外的所有变量,即便是函数声明之后的那些声明,也都包含在闭包中。

第二点可以解释为什么当外部函数outerFunction的作用域消失之后,内部函数innerFunction还是可以访问innerValue和afterValue变量。

 

 posted on 2017-07-15 09:45  F风  阅读(107)  评论(0编辑  收藏  举报