目录

  1. 前言
  2. 阐述闭包是什么?
  3. 函数的创建和执行看闭包(引述:堆栈、EC、AO、VO、scope)
  4. 闭包的作用以及在项目中的引用场景,以及带来的问题
  5. 闭包引发的高级编程技巧,在框架源码中的使用,或者自己写类库的怎么使用的
  6. 结束语
  7. 题外话

    前言

    不管是初级、中级的前端面试中,还是高级的前端面试中,闭包这个问题都会被拿来考验面试者。不同能力的面试者对这个问题的回答也是差别比较大的,
    常见的面试问答,有如下几种场景。

    青铜面试者

    闭包是xx…。它的危害xx…。

    闭包1.jpeg

    钻石面试者

    闭包是xx…。它的特点是xx…,它的危害xx…。我们日常怎么使用xx…。
    闭包2.png

这两类的面试者是非常常见的,不能说回答的不好,但是回答的也不能算惊艳,哪如何回答好闭包的问题了,往下看。
闭包3.jpeg

1. 阐述闭包是什么?

  • 官方说法:闭包就是指有权访问另一个函数作用域中的变量的函数。
  • MDN 说法:闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。 环境由闭包创建时在作用域中的任何局部变量组成。
  • 自我理解:把函数执行,形成私有上下文,并且保存和保护私有变量的机制,称之为“闭包” ,它是一种机制。

2. 函数的创建和执行看闭包(引述:堆栈、EC、AO、VO、scope)

浏览器在加载页面会把代码放在栈内存( ECStack )中执行,函数进栈执行会产生一个私有上下文( EC ),此上下文能保护里面的使用变量( AO )不受外界干扰,并且如果当前执行上下文中的某些内容,被上下文以外的内容占用,当前上下文不会出栈释放,这样可以保存里面的变量和变量值,所以我认为闭包是一种保存和保护内部私有变量的机制。

函数创建

  1. 创建一个堆:储存代码字符串和对应的键值对。
  2. 初始化当前函数的作用域:[[ scope ]] = 所在上下文EC中的变量对象 VO / AO。

函数执行

  1. 形成私有上下文,函数每一次执行 都是从新形成一个全新的私有上下文,和之前执行产生的上下文没有必然的联系。
  2. 进栈执行
  3. 创建 AO
  4. 初始化作用域链[[ scopechain ]]:< EC < FN >, 作用域< ECXXX >>或者也可以这样理解< AO, VO(G) >
  5. 初始化 this
  6. 初始化 arguments
  7. 形参赋值
  8. 变量提升
  9. 代码执行
    1. 遇到变量就先看是否是自己私有的,不是自己私有的按照作用域链上查找,如果不是上级的就继续线上查找,,直到 EC(G),变量的查找其实就是一个作用域链的拼接过程,拼接查询的链式就是作用域链。

正常情况下,代码执行完成之后,会有三类情况。

  • 当前上下文的某些东西被上下文以外的某些东西占用,那么当前上下文就不会被释放,就形成了闭包。
  • 如果没有被占用就是执行完成之后就被释放,不会形成闭包。
  • 除了这上面两种情况还有一种情况是,上下文没有被占用,但是要紧接着被用一次,这样没有用完之前是不能释放的,用完在释放,这样就形成了一个临时不被释放闭包。

3. 闭包的作用以及在项目中的引用场景,以及带来的问题

函数执行会形成全新的私有上下文,这个上下文可能被释放,也可能不被释放,不论是否被释放,它的作用是:

  • 保护:划分一个独立的代码执行区域,在这个区域中有自己私有变量存储的空间,而用到的私有变量和其它区域中的变量不会有任何的冲突(防止全局变量污染)
  • 保存:如果上下文不被销毁,那么存储的私有变量的值也不会被销毁,可以被其下级上下文中调取使用

在实际的项目中,会基于闭包把自己编写的模块内容包裹起来,这样编写就可以保护自己的代码是私有的,防止和全局变量或者是其他的代码冲突,这一点是利用保护机制。
在没有使用 ES6 的 let 之前,我们循环处理事件绑定,在事件触发需要用到引所值的时候,我们基于闭包,把每一轮循环的引所值保存起来,这样来实现我们的需求。只不过现在基于let会产生块级作用域来保护需要保存的内容(机制类似于闭包)。

但是不建议过多的使用闭包,因为使用不被释放的上下文,是占用栈内存空间的,过多的使用会导致渲染页面变慢,所以要合理的使用闭包。

4. 闭包引发的高级编程技巧,在框架源码中的使用,或者自己写类库的怎么使用的

除了在这些传统的业务开发中会引用闭包,我之前在研究别人的源码和自己写一些插件的时候,往往会利用一些JS高阶编程技巧俩是吸纳代码的管理和功能的开发,他们的机制都是使用闭包,例如:惰性函数、柯里化函数、compose函数。

从上面这几个大的方面来回答闭包是一个不错的角度,理论、底层运行机制、实践,不仅能看出你基础能力的深度,也能看出你基础能力的广度。

结束语

如果文章中什么不对或者写的不好的地方,请大家多多指正,谢谢!码字不易,点个赞加个关注吧!
靓仔.gif

题外话

笔者在「深圳虾皮」,一家口碑还不错的东南亚电商公司,2021大量招人,机会多多!快来加入我们吧!

现在有想法,还是以后有想法的同学,都可以加我微信[stone—-999]!内推你加入我们的大家庭!