对闭包的理解(整理)

理解闭包,首先要理解JavaScript的作用域。

>
JavaScript中是没有块级作用域的。
>
变量的作用域有两种:全局变量和局部变量。
>
JavaScript语言的特殊之处,就在于函数内部可以直接读取全局变量

上代码:

var n = 99;
function f1(){
    alert(n);
}
f1();//99

以上函数,f1可以调用全局变量n;

但,函数外部是无法读取函数内部的局部变量。

function f1(){
    var n = 99;//去掉var,n就是一个全局变量,alert(n)就不会报错。
}
alert(n);//ReferenceError: n is not defined

那么如何去访问函数内部的变量呢?
要得到函数内部的局部变量,就需要使用闭包。通过一个函数来访问函数内部的局部变量。
闭包的概念:

  • 闭包就是函数的局部变量的集合,只是这些局部变量在函数返回后会继续存在。
  • 闭包就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。
  • 当在一个函数内定义另外一个函数就会产生闭包。

    function f1(){
        var n = 99;
        function f2(){
            alert(n);
        }
        return f2;//f2函数就是闭包,通过这个函数能访问函数内部的局部变量。
    }
    var result = f1();//result就是闭包f2函数
    result();//弹出99
    

闭包的用途是什么呢?

  1. 可以读取函数内部的变量。
  2. 让这些变量始终保持在内存中。

    function f1(){
        var n = 99;
        nAdd = function(){//nAdd是一个全局变量,而不是局部变量。nAdd的值是一个匿名函数,这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以再函数外部对函数内部的局部变量进行操作。
            n += 1;
        }
        function f2(){
            alert(n);
        }
        return f2;
    }
    var result = f1();
    result();//99
    nAdd();
    result();//100
    

    这就证明了,函数f1中的变量n一直保存在内存中,并没有在f1被调用后被自动清除。

为什么会这样呢?原因在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致F2始终在内存中,而f2的存在依赖于f1,由此f1也始终在内存中,不会在调用结束后,被垃圾回收机制回收。

闭包的注意点

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当做对象object使用,把闭包当做它的公用方法(public method),把内部变量当做它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

经典的闭包小案例

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function(){
        return function(){
            return this.name;
        };
    }
};
alert(object.getNameFunc()());//The Window

-

var name = "The Window";
var object = {
    name: "My Object";
    getNameFunc: functon(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};
alert(object.getNameFunc()());//My Object

-

function fun(n, o){
    console.log(o);
    return {
        fun: function(m){
            return fun(m, n);
        }
    };
}
var a = fun(0);//undefined
    a.fun(1);//0
    a.fun(2);//0
    a.fun(3);//0

var b = fun(0).fun(1).fun(2).fun(3);//undefined,0,1,2

var c = fun(0).fun(1);//undefined,0
    c.fun(2);//1
    c.fun(3);//1

热评文章