什么是闭包呢?本文就这个问题进行简短的介绍。但了解闭包之前,我们先了解函数的定义和调用过程都发生了什么。
在函数(复杂数据类型)定义阶段,先是开辟存储空间(堆)将函数体以字符串的形式原原本本的存储起来,而将存储空间的地址交给了函数名即变量名。
在函数调用阶段,通过函数名找到存储空间,此时开辟一块执行空间。在执行空间内进行预解析,对形参进行赋值;将对应的函数体复制过来并执行;当执行完毕之后,销毁执行空间。如下图1-1:
另外,js作用域分为全局(外部)和局部(内部),且内部作用域的变量可以获得内部作用域和包含当前作用域的外层作用域的变量,反之则不成。在不同的函数作用域中也是不能相互访问彼此变量。
那么如果想在一个函数内部有限权访问另一个函数内部的变量该怎么办呢?依照变量访问的思路,可以通过在一个函数作用域内事先设置一个函数,也就是外层里面包裹着内层,当外层执行完毕,里层函数调用外层作用域的变量从而实现变量的使用。这也就是闭包的使用思路,一言蔽之,就是在一个函数内部创建另一个函数。
就好比,一个黑盒子里我们虽然无法直接看到里面装了什么,但是通过事先放置在其中的摄像机之类的工具,同样可以实现观察里面包含了什么物品。黑盒子就是外层函数,摄像机就是内层函数,里面的物品就是我们从外不作用域无法访问的变量。
例如下图1-2:
在上面的例子中,在OutFn( )执行后,把OutFn( )的返回值InFn( )赋值给res,相当于res= function InFn(){console.log(num)},最后调用res( )。
按普通函数生命周期来看,当OutFn()执行完毕,其执行空间应该被销毁释放。但是由于内部函数InFn()存在引用OutFn()的变量num的情况,使得InFn()的存储空间未被销毁,进而导致OutFn()的执行空间没被销毁。
由此,我们可以看出闭包函数产生的条件有:
1、存在函数嵌套的关系,即外部行数包裹内部函数
2、内部函数引用了外部函数的变量
3、内部函数在外部被变量接收并调用
同时也不难看出,闭包实现了:
1、函数外间接操作内部变量
2、本应该被销毁的变量被延长了生命周期
3、正因为第二点,使得被占据的内存的不到释放
闭包应用:
SetTimeout setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果
关键字:闭包 内部函数 内存泄漏
浅谈Js闭包
最新推荐文章于 2023-06-21 09:42:03 发布