【前端入门笔记17】闭包

126 阅读2分钟

什么是闭包?

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。

当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,就会形成闭包。

之所以中文叫“闭包”,是因为通过这种形式,将数据跟外部环境“隔离封闭起来”,在外部状态发生变化时,还能访问到某个内部状态里,所以叫“闭包”。

闭包的常见形式

  1. 将函数作为返回值(最为常见)👇
function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();
  1. 直接执行内部函数👇
function outer(){
	const local = 1
	function inner(){
		console.log(local)
	}
	inner()
}
outer() //1
  1. 间接执行内部函数👇
function outer(){
	const local = 1
	function inner(){
		console.log(local)
	}
	fn(inner)
}
function fn(args){
	args()
}
outer() //1

为什么能形成闭包?

闭包的形成离不开两个概念:作用域将函数作为值传递

作用域(词法作用域)

作用域是值和表达式可以被访问到的上下文,如果不在作用域中,那么值和表达式就是不能被访问的。子作用域可以访问父作用域,指的是通常沿着链式的作用域链查找,而不能从父作用域引用子作用域中的变量和引用。

词法作用域是由函数声明时所在的位置决定的,而闭包是词法作用域形成的自然结果。

将函数作为值传递

JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处。

由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民。

闭包的用途是什么?

闭包的用途,就是通过闭包返回的函数,让外部可以访问本应该消失的外层函数的数据。

闭包的缺点是什么?

因为闭包的形成,实际上是因为创建了多个函数实例,通过实例来维持它所在的词法环境。所以闭包的缺点是比较耗费内存。