js闭包,渣滓接纳,内存走漏

1.闭包的观点

闭包:指有权接见另一个函数作用域中的变量的函数。
闭包的实质是将函数内部和函数外部连接起来的一座桥梁。

2.怎样建立闭包

例1:

function outer(){
    var a=1;
    function inner(){
        a++;
      alert(a);
    }
    return inner;
}
var f1=outer();//建立了一个闭包,f1能接见outer函数中的变量
f1();//弹出2.

这段代码的特性在于:
1.函数inner嵌套在函数outer内部
2.函数outer返回函数inner,并将值赋给了f1
例2:

// 完成累加:体式格局1
var a = 0;
var add = function(){
    a++;
    console.log(a)
}
add();
add();
//体式格局2 :闭包
var add = (function(){
    var  a = 0;
    return function(){
        a++;
        console.log(a);
    }
})();
console.log(a); //undefined
add();
add();

//体式格局2的长处:削减全局变量,将变量私有化

3.闭包与变量的关联

闭包只能获得包括函数中任何变量的末了一个值。
例:

function f1() {
    var res = new Array();
    for(var i=0;i<10;i++){
        res[i] = function() {
            alert(i);
        };
    }
    return res;
}
var f2 = f1();
var f2 = f1();
f2[0]();//alert 10
//并不会返回一次弹出0-9的函数数组,而是弹出10个10的函数数组,由于res中每一个函数的作用域中都保存着f1()的运动对象,援用的是同一个变量i,当f1()返回后i的值为10

解决方法:

function f1() {
    var res = new Array();
    for(var i=0;i<10;i++){
        res[i] = (function(num) {
            return function (){
                alert(num);
            }
        })(i);//函数参数按值通报
    }
    return res;
}
var f2 = f1();
var f2 = f1();
f2[0]();//alert 0

4.内存泄漏及解决方案

渣滓接纳机制

说到内存治理,天然离不开JS中的渣滓接纳机制,有两种战略来完成渣滓接纳:标记消灭 和 援用计数;

标记消灭:渣滓收集器在运转的时刻会给存储在内存中的一切变量都加上标记,然后,它会去掉环境中的变量的标记和被环境中的变量援用的变量的标记,今后,假如变量再被标记则示意此变量预备被删除。 2008年为止,IE,Firefox,opera,chrome,Safari的javascript都用使用了该体式格局;

援用计数:跟踪纪录每一个值被援用的次数,当声明一个变量并将一个援用范例的值赋给该变量时,这个值的援用次数就是1,假如这个值再被赋值给另一个变量,则援用次数加1。相反,假如一个变量脱离了该值的援用,则该值援用次数减1,当次数为0时,就会守候渣滓收集器的接纳。

这个体式格局存在一个比较大的题目就是轮回援用,就是说A对象包括一个指向B的指针,对象B也包括一个指向A的援用。 这就能够形成大批内存得不到接纳(内存泄漏),由于它们的援用次数永久不多是 0 。初期的IE版本里(ie4-ie6)采纳是计数的渣滓接纳机制,闭包致使内存泄漏的一个缘由就是这个算法的一个瑕玷。

我们晓得,IE中有一部分对象并非原生额javascript对象,比方,BOM和DOM中的对象就是以COM对象的情势完成的,而COM对象的渣滓接纳机制采纳的就是援用计数。因而,虽然IE的javascript引擎采纳的是标记消灭战略,然则接见COM对象依然是基于援用计数的,因而只要在IE中设想COM对象就会存在轮回援用的题目!

例子:

window.onload = function(){
    var ele = document.getElementById("id");
    ele.onclick = function(){
        alert(ele.id);
    }
}

这段代码为何会形成内存泄漏?

ele.onclick = function(){
        alert(ele.id);
    }

实行这段代码的时刻,将匿名函数对象赋值给ele的onclick属性;然后匿名函数内部又援用了ele对象,存在轮回援用,所以不能被接纳。

解决方法:

window.onload = function(){
    var ele = document.getElementById("id");
    var id = ele.id; //消除轮回援用
    ele.onclick = function(){
        alert(id); 
    }
    ele = null; // 将闭包援用的外部函数中运动对象消灭
}

5.总结闭包的优瑕玷

长处:

  • 当须要一个变量常驻内存时,闭包能够完成一个变量常驻内存 (假如多了就占用内存了)

  • 防止全局变量的污染

  • 私有化变量

瑕玷:

  • 由于闭包会照顾包括它的函数的作用域,因而会比其他函数占用更多的内存

  • 引发内存泄漏

    原文作者:Evan_Chen
    原文地址: https://segmentfault.com/a/1190000004682028
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞