现在很多人在面试前端开发时,都会被问到闭包。那闭包是什么呢?当我们遇到此类问题时,应该如何回答呢?就我而言,我觉得如果要回答闭包问题,就得先从作用域链开始讲起。
在谈及作用域链时,先谈下什么是作用域。作用域有以下几点特征:
- 当我们在函数中,声明一个变量或者函数的时候,就会把这条数据存入到该函数的作用域中
- 在作用域中,存储的是该函数可以访问到的数据
- 在js的es5中才会出现作用域问题
而以此衍生出的作用域链,网上比较官方的说法是:是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
其通俗的解释就是:当我们在函数中,调用一个变量,或者函数的时候,首先第一步,会在本作用域中去查找这条数据,如果找不到的话,就会去找父级的作用域的数据,如果在一层层的父级中,也找不到相关的数据,就会去查找全局作用域,如果在全局中也找不到,就报错。
好了,作用域链讲清楚了。现在可以开始讲闭包。关于闭包,目前行业里比较流行的说法有两个:
- 函数嵌套函数
- 函数嵌套函数,子函数可以访问父函数作用域里的数据。父级不能访问子元素作用域里的数据
目前认可度更高的说法是第2个,体现了闭包和作用域链之间的关系。如果你面试的时候,面试官可能说你说的不太对。那是因为目前有人又提出了新的说法。
也就是第3种说法:函数嵌套函数,子函数可以访问父函数作用域里的数据。父级不能访问子元素作用域里的数据,且必须要在父函数里加上return,把子函数return出去。这相当于给外部提供一个调用子函数的接口。每次调用子函数,都能够调用到父级作用域里的数据。这一种说法涉及到了垃圾回收机制。
垃圾回收机制中有这么一个说法:局部作用域中的数据,当函数彻底执行完成,再没有调用它的内容,它作用域中的数据就会被销毁。
根据第3种说法,给父函数加了return,一直都在调用return,那父函数作用域内的数据只有在关闭网页的时候才能被销毁。