Javascript学习总结(二) 闭包

闭包的特性

    由于在Javascript中,函数是对象,对象是属性的集合,而属性的值可以是对象,则在函数内定义函数成为理所当然,如果在函数fun内声明函数inner,然后在函数外部调用inner,这个过程就产生了闭包。闭包的三个特性:
    1、函数嵌套函数
    2、函数内部可以引用函数外部的参数
    3、参数和变量不会被垃圾回收机制回收

闭包的用途

    通过使用闭包,我们可以做很多事情。比如模拟面向对象编程风格(私有变量,私有成员);更优雅,更简洁的表达代码;在某些方面提升代码的执行效率(匿名自执行函数)。
    1、希望一个变量常驻内存。
    2、避免全局变量的污染。
    3、私有成员的存在(用关键字var 函数内部定义变量,在外部除非使用抛出的方法使用该变量,否则就无法访问该变量)。 

匿名自执行函数

    所有的变量不加var关键字,则默认会添加到全局对象的属性上去。这样的临时变量加入到全局对象上去有很多的坏处。比如:别的函数可能误用这些变量;造成全局变量国语庞大,影响访问速度(因为变量的取值是从原型链上遍历的)。除了每次都使用关键字var外,我们在实际情况下经常会遇到这样的情况,即有的函数只需要执行一次,其内部变量无需维护,那么我们就可以使用闭包。
    var datamodel={
        table:[],
        tree:{}
    };
    (function (dm){
        for(var i=0;i < dm.table.rows; i++){
            var row = dm.table.rows[i];
            for(var j=0;j <row.cells; i++){
                drawCell(i,j);
            }
        }
    //build dm.tree
})(datamodel);
我们创建了一个匿名函数,并立即执行它,由于外部无法引用它内部的变量,因此在执行完之后很快就会被释放,最主要的是这种机制不会污染全局对象。

内存泄漏

    在不同的javascript解释器实现中,由于解释器本身的缺陷,使用闭包可能造成内存泄漏问题,内存泄漏是比较严重的问题,会严重影响浏览器的运行速度,降低用户体验,甚至会造成浏览器无响应等现象。
    javascript的解释器具备垃圾回收机制,一般采用的是引用计数的形式,如果一个对象的引用计数为0,则垃圾回收机制会将其回收,这个过程是自动的。但是有了闭包之后这个过程就往往变的复杂起来,在闭包中。因为局部变量可能在将来的某些时刻被使用,因此垃圾回收机制不会处理这些被外部引用的局部变量,而如果出现循环引用,即对象A引用对象B,B引用C,C引用A,这样的情况使得垃圾回收机制得出其引用计数不为0的结论,从而造成内存泄漏。