CLAYYA

乌贼馋辣鱼的博客

闭包

2024-11-28

闭包

简单来说,闭包让你能够在一个函数内部定义另一个函数,并且这个内部函数能够访问外部函数的变量,即使外部函数已经执行完毕。

一般函数的词法环境在函数返回后就被销毁,但是闭包会保存对创建时所在词法环境的引用,即便创建时所在的执行上下文被销毁,但创建时所在词法环境依然存在,以达到延长变量的生命周期的目的。

使用闭包,一可以读取函数中的变量,二可以将函数中的变量存储在内存中,保护变量不被污染。而正因闭包会把函数中的变量值存储在内存中,会对内存有消耗,所以不能滥用闭包,否则会影响网页性能,造成内存泄漏。当不需要使用闭包时,要及时释放内存,可将内层函数对象的变量赋值为 null。

原理

函数执行分成两个阶段(预编译阶段和执行阶段)。在预编译阶段,如果发现内部函数使用了外部函数的变量,则会在内存中创建一个“闭包”对象并保存对应变量值,如果已存在“闭包”,则只需要增加对应属性值即可。

利用了函数作用域链的特性,一个函数内部定义的函数会将包含外部函数的活动对象添加到它的作用域链中,所以尽管外部函数已经销毁,但是其作用域链被保存。

使用场景

  • setTimeout:原生的 setTImeout 传递的第一个函数不能带参数,通过闭包可以实现传参效果。
  • 回调:定义行为,然后关联到用户事件上,代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。
  • 防抖函数、记忆函数等。
  • 私有变量的数据封装。
  • 延长变量的生命周期。
  • 防止全局变量污染。典型应用是模块封装,在各模块规范出现之前,都是用这样的方式防止变量污染全局
    在循环中创建闭包,防止取到意外的值。