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