闭包

闭包,猎取一个部分作用域里变量的接见权限,涉及到作用域栈、实行上下文、渣滓接纳机制、内存驻留以及机能题目,闭包割断作用域栈发生的渣滓接纳事宜,完成变量的内存驻留。重要运用场景在须要积累效应、反复轮回事宜、前后事宜相干等。因此,为防止发生严峻的机能题目,在完成事宜使命后要把闭包置为null,开释内存。

这里引见JS中作用域栈的特征,即先进后出,全局作用域位于栈底,部分作用域根据编译、实行递次顺次入栈,实行终了顺次出栈,对变量举行渣滓接纳,开释内存。相识此特征,应用全局作用域一直位于栈底,而且老是末了完成渣滓接纳,只要在部分作用域中装载具有全局效应的作用域,阻断渣滓接纳,就完成了闭包的设想。

  • 示例1

function foo(x) {
    var tmp = 3;
    return function (y) {
        console.log(x + y + tmp);
        x.memb = x.memb ? x.memb + 1 : 1;
        console.log(x.memb);
    }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);
  • 示例2

function foo(x) {
    var temp = 3;
    return function (y) {
        console.log(x + y + (++temp));
    }
}
var bar = foo(2);
bar(10);
  1. 示例3

function badClosureExample() {
    var as = document.querySelectorAll('a');
    for (var i = 0; i < 4; i++) {
        as[i].onclick = new popNum(i);
        function popNum(oNum) {
            return function () {
                alert('单击第' + oNum + '个');
            }
        }
    }
}
badClosureExample();
  1. 示例4

 function badClosureExample() {
    var as = document.querySelectorAll('a');
    for (var i = 0; i < 4; i++) {
        (function (i) {
            as[i].onclick = function () {
                alert('单击第' + i + '个');
            }
        })(i);
    }
}
badClosureExample();

1、将变量 i 保留给在每一个段落对象(p)上

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].i = i;
        pAry[i].onclick = function () {
            alert(this.i);
        }
    }
}
init();

2、将变量 i 保留在匿名函数本身

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (pAry[i].onclick = function () {
            alert(arguments.callee.i);
        }).i = i;
    }
}
init();

3、加一层闭包,i 以函数参数情势传递给内层函数

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function (i) {
            pAry[i].onclick = function () {
                alert(i);
            }
        })(i);//挪用时参数
    }
}
init();

4、加一层闭包,i 以部分变量情势传递给内层函数

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        (function () {
            var index = i;//挪用时部分变量
            pAry[i].onclick = function () {
                alert(index);
            }
        })();
    }
}
init();

5、加一层闭包,返回一个函数作为相应事宜(注重与3的纤细区分)

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = function (i) {
            return function () { //返回一个函数
                alert(i);
            }
        }(i)
    }
}
init();

6、用Function完成,实际上每发生一个函数实例就会发生一个闭包

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick = new Function("alert(" + i + ")");
        //new一次就发生一个函数实例
    }
}
init();

7、用Function完成,注重与6的区分

function init() {
    var pAry = document.getElementsByTagName("p");
    for (var i = 0; i < pAry.length; i++) {
        pAry[i].onclick =Function("alert(" + i + ")");
    }
}
init();
  • 示例5

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

function outerFun() {
    var a = 0;

    function innerFun() {
        a++;
        alert(a);
    }

    return innerFun; //注重这里
}
var obj = outerFun();
obj(); //效果为1
obj(); //效果为2
    原文作者:whjin
    原文地址: https://segmentfault.com/a/1190000009009575
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞