1、什么是闭包
浅理解:方法里面返回一个方法。
var a = 1;
// 匿名的立即执行函数,因访问了全局变量a,所以也是一个闭包
(function test (){
alert(a);
})()
正理解:如果一个函数访问了此函数的父级及父级以上的作用域变量,那么这个函数就是一个闭包。
function a(){
let a1=1;
return function(){
return a1;
}
};
2、闭包的存在的意义
2.1 延长局部变量的生命周期(由于局部变量会被清除)
补充:全局变量 局部变量
let a='小明'; //全局变量
function fn1(){
let b = 1;
console.log(a) //可以拿到
}
console.log(b); //报错
fn1();
解析(全局、局部变量):js在执行程序的时候 会生成一个 AO(active object),当运行结束的时候会清除回收这个 AO,即也清除了这个AO里面的方法和变量。回到题目中,a的变量是存放在script全局作用域中的而变量b的是存放在AO中也就是局部作用域中的,函数fn1运行结束后会清除b,所以在全局打印不出b。
js的垃圾回收机制:
- 如果一个对象不再被引用,那么这个对象就会被GC回收。
- 如果两个对象互相引用,而不再被第三者所引用,那么这两个对象都会被回收。
2.2 创建私有环境(私有作用域)
(1)vue是一个单页应用,会有很多组件,每个组件都会有一个data,也就是闭包,也就是一个私有的环境(作用域),它们可以互不干扰。
Vue data() 为什么是一个函数?
这个其实是一个闭包,
data(){
return{
}
}
2.3 通过创建闭包,让函数内部返回出对应的数据,让函数外部可以访问到函数的部可供访问的数据。
3、使用闭包创建私有环境的实践
//闭包函数,外面不可以访问里面,创建一个私有环境,return给什么,外面才能拿什么
let makeCounter = function (){
let num = 0;
function changeBy(val){
num+=val; //num=num+val
};
//创建闭包
return{
add:function(){
changeBy(1)
},
reduce:function(){
changeBy(-1)
},
value:function(){
return num
}
}
};
let counter1=makeCounter(); //创建一个
let counter2=makeCounter(); //又创建一个
counter1.add();
counter1.add();
counter2.add();
// counter1,counter2 各自独立空间,互不干扰,都有独立的词法作用域
console.log(counter1.value()); // 2
console.log(counter2.value()); // 1
4、闭包的优点与缺点
优点
- 可以减少全局变量的定义,避免全局变量的污染
- 能够读取函数内部的变量
- 在内存中维护一个变量,可以用做缓存
缺点
- 将局部变量常驻内存,内存消耗增大。使用完变量后,手动将它赋值为null。
- 由于外部可以访问到函数内部的值,可改变函数内部的值。
- 性能损耗。