参考链接:
彻底搞懂JS闭包各种坑
闭包,作用域链,垃圾回收,内存泄露

定义:

能够访问另一个函数作用域的变量的函数。清晰的讲:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量。

图片说明
inner能访问到outer作用域的变量,所以inner就是一个闭包函数

被内部函数访问的外部函数的变量可以保存在外部函数作用域内而不被回收

一般来说,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域。但是,闭包的情况又有所不同

为什么闭包函数可以访问其他函数的作用域

基本变量的值一般都是存在栈内存中,而对象类型的变量的值存储在堆内存中,栈内存存储对应空间地址。基本的数据类型: Number 、Boolean、Undefined、String、Null。
图片说明
1、首先执行fn,此时在全局执行环境
2、进入fn,进入fn的执行环境
3、进入fn1,此时栈内存就会push一个fn1的执行环境,这里面没有定义别的变量,所以程序在访问变量时,是向底层栈一个个找,如果找到全局执行环境都没有对应边梁,则undefined
4、fn1执行完毕,fn1的环境被销毁,执行完fn,fn的执行环境也会被销毁,只剩全局的执行环境

当inner执行完,inner和outer的执行环境才会被销毁掉。

因此闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内容,过度使用闭包,会导致内存占用过多。

坑点1:引用的变量可能发生变化

因为是在循环结束之后,才被输出,所以输出的是10,10,10
图片说明

此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样
图片说明

坑点2:this指向问题

// 因为里面的闭包函数是在window作用域下执行的,也就是说,this指向windows
图片说明

坑点3:内存泄漏问题

1// 这样会导致闭包引用外层的el,当执行完showId后,el无法释放

图片说明

JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.

图片说明