「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」
前言
前端面试三大内容,作用域、闭包、原型链,可想而知闭包的重要程度,但是讲实话通过我工作的经验来看闭包在项目中使用的真的不算多,也可能是我做的项目太简单了,也可能是我根本不了解闭包,因此用的比较少。但闭包真的很重要,起码对面试来说,所以不管因为什么都要把闭包给学明白了。
什么是闭包
到底什么是闭包呢?
闭包其实就是指那些可以访问自由变量的函数(自由变量就是既不是函数的参数也不是函数的局部变量的变量)
上面的闭包定义是理论上的定义,实际的定义必须满足以下两点
- 当创建它的上下文已经销毁了但是它仍然存在
- 它可以访问自由变量 只有满足了上面两点才是实际意义上的闭包
例子
var arr = [];
for (var i = 0; i < 3; i++) {
arr[i] = function () {
console.log(i);
};
}
arr[0]();
arr[1]();
arr[2]();
上面代码在面试中经常被问到,上面的三个输出结果都是3,但其实我们想要的是输出0,1,2,要怎么改才能实现输出的结果是0,1,2呢,如下代码
var arr = [];
for (let i = 0; i < 3; i++) { //这里我们只需要把var改成let即可
arr[i] = function () {
console.log(i);
};
}
arr[0]();
arr[1]();
arr[2]();
同样,除了上面的var改成let关键字,还可以利用闭包的特性,也就是上下文已经销毁了但它依然存在,并且可以使用父函数的变量(也就是自由变量),代码如下
var arr = [];
for (let i = 0; i < 3; i++) { //这里我们只需要把var改成let即可
arr[i] = (function (i) {
return function(){
console.log(i)
}
})(i);
}
arr[0]();
arr[1]();
arr[2]();
更容易记忆的闭包的定义(实际应用中)
- 函数里边嵌套的子函数
- 子函数调用父函数的局部变量(也可以叫做私有变量)
- 通过return将子函数暴露在全局变量 这个子函数就是闭包
var a=1;
function fun(){
var a=2;
return function(){
a++;
console.log(a);
}
}
var fun1 = fun();
fun1();//3
闭包的优缺点
优点
-
可以让局部变量长期保存在内存中
-
避免污染全局变量
-
可以读取父函数的局部变量 缺点
-
如果乱使用闭包可能会造成内存泄露,并且由于函数的嵌套会影响性能
-
由于闭包被return到了父函数外部,可能出现改变父函数内部变量的情况