闭包

一:了解闭包首先要了解嵌套函数的词法作用域规则。

var scope = "global scope";         /*全局变量*/
function checkscope() {             
    var scope = "local scope";      /*局部变量*/
    function f() {
        return scope;               /*在作用域中返回这个值*/
    }
    return f();
}
console.log(checkscope());           /*"loacl scope*/

checkscope()函数声明了一个局部变量,并定义了一个函数f(),函数f()返回了这个变量的值,最后将函数f()的执行结果返回。

改动一下代码,返回什么?

var scope = "global scope";         /*全局变量*/
function checkscope() {
    var scope = "local scope";      /*局部变量*/
    function f() {
        return scope;               /*在作用域中返回这个值*/
    }
    return f;
}
console.log(checkscope()());          /*返回什么*/

在这段代码里,将函数内的一对圆括号移动到了checkscope()之后。checkscope()现在仅仅返回函数内嵌套的一个函数对象,而不是直接返回结果。在定义哈数的作用域外部,调用这个嵌套的函数。

二:实现闭包

uniqueInteger.counter = 0;
function uniqueInteger() {
    return uniqueInteger.counter++;
}
console.log(uniqueInteger());

这个函数使用自身的一个属性来保存每次返回的值,以便每次调用都能跟踪上次的返返回值。但是这个做法有个问题,就是恶意代码可能将计数器重置或者把一个非整数付给他,导致函数不一定产生“唯一”的“整数”。而闭包能够捕捉到单个函数调用的局部变量,并将这些局部变量用作私有状态。

var uniqueInteger = (
    function () {
        var counter = 0;
        return function () {
            return counter++
        };
    }()
);
console.log(uniqueInteger());

这段代码定义了一个立即调用的函数(函数的开始带有左圆括号),因此是这个函数的返回值赋值给变量uniqueInteger。

这个函数返回另一个函数,这是一个嵌套函数,我们将它赋值给uniqueInteger,嵌套的函数是可以返回作用域内的变量的,而且可以访问外部函数中定义的counter变量。当外部函数返回以后,其他代码都无法访问counter变量,只有内部函数才能访问到他。

像counter一样的私有变量不是只能用在一个单独的闭包内,在同一个外部函数内定义的多个函数也可以访问它,这与多个嵌套函数都共享一个作用域链。

function counter() {
    var n = 0;
    return {
        count:function () {
            return n++;
        },
        reset:function () {
            n = 0;
        }
    };
}
/*创建2个计数器*/
var c = counter();
var d = counter();

console.log(c.count());     /*0*/
console.log(d.count());     /*0*/

console.log(c.reset());     /*重置了*/

console.log(c.count());     /*0:将c重置了*/
console.log(d.count());     /*1*/

counter()函数返回一个“计数器”对象,这个对象包含两个方法:count返回下一个整数,reset将计数器重置为内部状态。首先要理解,这两个方法都可以访问私有变量n。再者,每次调用counter()都会创建一个新的作用域链和一个新的私有变量。因此,如果调用counter()两次,则会得到两个计数器对象,而且彼此包含不同的私有变量,调用其中一个计数器对象的count和reset不会影响到另一个对象。

原文地址:https://www.cnblogs.com/QianBoy/p/7632996.html