函数编程-在循环体和异步回调中慎重使用闭包(closure)

由于闭包具有持久性,生成的闭包不会立即被销毁,因此它会持续占用系统资源。如果大量使用闭包,将会造成系统资源紧张,甚至导致内存溢出等错误。

/*   内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束,由于浏览器垃圾回收方法有bug,会产生内存泄露 */
/**
 * 把数组类型的参数中每个元素的值分别封装在闭包结构中,
 * 然后把闭包存储在一个数组中,并返回这个数组。
 */
function f(x) {
    var a = [];
    for (var i = 0; i <  x.length; i++) {
        var temp = x[i];
        a.push(function() {
            /* 闭包中temp并不是固定的,它会随着根据函数运行环境中的变量temp的值变化而更新,
            这样会导致数组元素的值都是字符‘c’,而不是a,b,c。 */
            /*由于循环变量i递增之后,最后的值是3,x[3]超出了数组的长度,所以运行结果是undefined*/
            console.log(temp + " " + x[i]);
        });
    }
    return a;
}

function e() {
    var a = f(["a", "b", "c"]);
    for (var i = 0; i < a.length; i++) {
        a[i]();
    }
}
e(); // 'c undefined'*3


(放进a数组里面的temp 和 x[i] 依旧是 变量
---------------------------------------解决方案------------------------------------------------------------------

function f(x) {
    var a = [];
    for (var i = 0; i <  x.length; i++) {
        var temp = x[i];
        /* 为闭包再包裹一层函数,然后运行函数,并把外界动态值传递给它,
        这个函数接收这些值后传递给内部的闭包函数,从而阻断了闭包与最外层函数实时联系 */
        a.push((function(temp, i) {
            return function() {
                console.log(temp + " " + x[i]);
            }
        })(temp, i));
    }
    return a;
}

function e() {
    var a = f(["a", "b", "c"]);
    for (var i = 0; i < a.length; i++) {
        a[i]();
    }
}
e();
方式一:调用函数,得到返回值,强制函数直接量执行再返回一个引用,引用再去调用执行
方式二:调用函数,得到返回值,强制运算符使函数调用执行


你可能感兴趣的:(改善JS编程建议)