一.闭包的概念
<script>
//js作用域: 全局作用域和局部作用域
/* function foo() {
var a = 10;
}
foo();
console.log(a); → 10 */
/* function bar() {
var num = 1;
function baz() {
num++;
console.log(num);
}
baz();
}
bar(); → 2
bar(); → 2 */
function bar() {
var num = 1;
function baz() {
num++;
console.log(num);
}
return baz;
}
var foo = bar(); //按照之前的认知,bar执行完毕之后,num这个局部变量应该销毁
foo(); // → 2 但foo能正常执行,没有报错,证明num并未销毁,这是为什么呢?
foo(); // → 3 就是因为JS闭包这个特性的存在
//概念:在一个函数的外部能够访问该函数局部变量的函数
</script>
二.闭包的应用
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
//请用闭包实现:点击li,输出对应的索引
let aLi = document.querySelectorAll("li");
//非闭包写法************
/* for (let i = 0; i < aLi.length; i++) {
aLi[i].onclick = function () {
console.log(i);
};
} */
//闭包写法**************
/* for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = (function (i) {
return function () {
console.log(i);
};
})(i);
} */
for (var i = 0; i < aLi.length; i++) {
(function (i) {
aLi[i].onclick = function () {
console.log(i);
};
})(i);
}
</script>
</body>
三.闭包的优缺点
<script>
//优点
//1.变量能常驻内存
//2.减少全局变量的定义
//3.创建命名空间
let obj = (function () {
let a = 1;
function foo() {}
let b = 2;
function bar() {}
return {
a,
b,
foo,
};
})();
//缺点 闭包使用不当,会造成内存污染,正常无法被垃圾回收机制清掉,IE低版本会造成内存泄漏
</script>
四.垃圾回收机制
<script>
//1. 标记清除
function foo() {
var a = 10;
var b = 20;
}
foo();
//2. 引用计数
/* var obj = {};
obj = null; */
var obj1 = {};
var obj2 = {};
obj1.a = obj2;
obj2.b = obj1;
</script>
五.闭包面试题
<script type="text/javascript">
//*****************************************
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
},
};
}
/*var a = fun(0);
a.fun(1); //fun(1,0)
a.fun(2);//fun(2,0);
a.fun(3);//fun(3,0);*/
//var b = fun(0).fun(1).fun(2).fun(3);
/* var c = fun(0).fun(1);
c.fun(2);
c.fun(3); */
//*******************************************
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
}
};
}
// var a = fun(0);a.fun(1);a.fun(2);a.fun(3);
// var b = fun(0).fun(1).fun(2).fun(3);
// var c = fun(0).fun(1);c.fun(2);c.fun(3);
var a = fun(0);
a.fun(1);
a.fun(2);
a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
//问:三行a,b,c的输出分别是什么?
</script>