对于前端人员面试,出现频率最多也是让人最头疼的就是面试官说:“请简单谈一谈你对闭包的理解”。对于这一个几乎快被人问烂的问题,屡屡出现在我们面试或被面试的过程中的原因很简单--我们一直都在接触闭包,却很少去正确地对待它。

因为闭包是因为JS的一些语言特性而形成的,所以在谈它之前我们首先要了解一下的知识点

1.执行上下文
2.作用域
3.垃圾回收机制
4.函数嵌套

本文只会简单的谈涉及到的内容,如果知识点有遗漏的同学可以自行google,接下来让我们进入正题!

1. 什么是闭包?

关于什么是闭包让我们先看看《高级程序设计》和《JavaScript权威指南》中的说法:

《高程》: 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数。

《权威指南》:和其他大多数现代编程语言一样,JavaScript也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。为了实现这种词法作用域,JavaScript函数对象的内部状态不仅包含函数的代码逻辑,还必须引用当前的作用域链。函数对象可以通过作用域链互相关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为“闭包”。

比较两种说法《高程》中的说法太过抽象,我比较倾向于《权威指南》中的说法,现在让我们剥茧抽丝,一步一步的解释这种说法。

2. 解释闭包,扫荡闭包理解过程中产生的知识点

我们知道“JavaScript中没有块级作用域”,所谓“块”,也就是大括号“{}”中间的语句(但是在ES6中已经引入块级作用域,这里不做讨论).我们还知道在JavaScript中,在函数里面定义的变量,可以在函数里面被访问,但是在函数外无法访问,这也就形成了函数作用域,即如下代码所示

var i = 1;
if(true){
    var j = 2;
}
console.log(i,j) // 1 2


function test(){
    var z = 3;
}

test();
console.log(z); //Uncau