闭包的概念
闭包是指有权访问另一个函数作用域中的变量的函数,本质也就是在函数里面返回一个函数
一般就是一个函数A,return其内部的函数B,被return出去的B函数能够在外部访问A函数内部的变量,这时候就形成了一个B函数的变量背包,
A函数执行结束后这个变量背包也不会被销毁,并且这个变量背包在A函数外部只能通过B函数访问。
闭包形成的原理
延长作用域链,当前作用域可以访问上级作用域中的变量
闭包解决的问题
能够让函数作用域中的变量在函数执行结束之后不被销毁,同时也能在函数外部可以访问函数内部的局部变量。
闭包带来的问题
由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。
所以使用完闭包后,可以通过对闭包 geta = null(下面代码) ,让垃圾回收器回收
实现一个简单的闭包
function fun(){
var a = 10;//fun函数作用域内部的变量
return ()=>{
return a;//在此可以访问到fun函数作用域的a
}
}
var geta = fun();
var a = geta();
console.log(a);//通过闭包我们就可以在fun函数外部访问到fun函数内部作用域的变量
闭包的作用
- 延迟变量的生命周期
- 创建出私有作用域 (如 vue中data返回一个对象)
- 闭包可以在函数外部访问到函数内部作用域的变量
- 闭包可以让访问变量不会被垃圾机制回收
因为受js链式作用域的影响,
- 子对象会一级一级向上寻找所有父对象的变量,反之不行。
- js中函数内部可以读取全局变量,函数外部不能读取函数内部的局部变量
闭包的应用场景
- 使用场景一:给对象设置私有变量并且利用特权方法去访问私有属性
function Fun(){
var name = 'tom';
this.getName = function (){
return name;
}
}
var fun = new Fun();
console.log(fun.name);//输出undefined,在外部无法直接访问name
console.log(fun.getName());//可以通过特定方法去访问
- 使用场景二:采用函数引用方式的setTimeout调用
setTimeout:接收两个参数,第一个参数可以是一段js代码,亦可以是一个函数,第二个参数是我们延迟执行第一个参数的时间(实际上不是延迟执行,而是延迟加入执行队列),在此我们要讨论的情况是第一个参数是一个函数的情况,我们传入的参数实际上是函数对象的引用,那这时候就不能向函数传参了,那么闭包就派上用场了
function fun(num){
var age = num;
return function(){
console.log(age);
}
}
var getAge = fun(200);//传入需要的参数,得到函数(闭包)的引用
var age = setTimeout(getAge,1000);//正确输出
- 防抖节流函数
- 单例模式
- 实现柯里化
- Vue中数据响应式Observer中使用闭包等。