闭包,很难下定义是什么,但又是一个进阶中高级开发的必备概念,今天就深入浅出的说说闭包是什么,如何在实际开发中应用闭包;
首先从字面上理解:闭,关住的意思,被封存在一个独立的空间;包,包裹包含;想象成一个书包,把文具书本放进去拉住拉链就形成了闭包;
官方给出的解释是能够读取其他函数内部变量的函数,定义在函数内部的函数,本质上是内部函数和外部函数连接的桥梁;
function A() {
let num = 0
return function () {
return num
}
}
let fn = A()
console.log(fn())
这就是一个闭包,函数内部返回一个函数,内部函数访问A函数的变量然后返回供外部使用。
闭包有一个很大的特点,就是可以记住诞生的环境,能访问当前执行上下文的变量和方法。执行环境会随着函数调用改变内部的变量和方法,闭包通过作用域链查找的时候,拿到的也是最新的;
闭包有两个保,一是保护私有变量不被污染,二是保存变量;
举一个经典案例
function A(a){
A = function (b){
console.log(a + b++)
}
console.log(a++)
}
A(1)
A(2)
这个打印结果为1,4,1很好理解,4是为什么呢;
首先函数第一次被调用的时候,创建AO对象,形参作为对象的属性,值为实参1,代码往下执行,A函数被重新赋值,打印a为1,a++,此时a已经变为了2;
第二次函数被调用时,因为A函数被重新定义,执行的则是function(b){},实参2传进去,b形参接收,console.log(a + b++)的时候,先查找当前作用域,没有a,则往上找,父函数内第一次被调用的时候,有a,拿到返回,所以2 + 2 = 4
可以总结,父函数调用会形成新的闭包,父函数的变量会存在内存中,第一次调用的a被第二次调用占用,函数没有被释放,会造成内存泄漏,所以闭包要谨慎使用;
但JS中很多代码都可以用闭包来进行优化精进,比如防抖和节流等等
如果对闭包还是不理解,那就死记硬三个条件
- 函数嵌套
- 访问所在的作用域
- 在所在作用域外被调用