JS之什么是闭包

206 阅读2分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

什么是闭包?

红宝书和MDN上的概念

红宝书闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数。 MDN:一个函数和对其周围状态的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。

通俗说,闭包其实就是一个可以访问其他函数内部变量的函数。即一个定义在函数内部的函数,或者直接说闭包是个内嵌函数也可以。

通常函数内部变量是无法被外部访问的,因为是局部变量,使用闭包,就可以让外部访问某一个函数内部变量的功能,而且这些内部变量的值始终可以保存在内存中。通过代码看一个例子

function fun1() {
  var a = 1;
  var b = 1;
  return function(){
    console.log(a);
  };
}
fun1();
var result = fun1();
result();  // 1

可以看到我们从外部拿到了a的值,理论上来说a这个变量应当是fun1执行完毕后直接就销毁掉,但是通过闭包的手段我们拿到了这个值1,同样也代表a这个变量保存在了内存之中。

为什么能拿到这个a呢,原因是根据作用域链,fun1里面返回的function可以访问到fun1的a变量,当通过外部函数(fun1)返回内部函数(function)的时候,即使外部函数(fun1)执行完毕,但是内部函数(function)还是可以访问到外部函数的变量,这些被内部函数用到的变量集合就是闭包,这个例子中foo的闭包就是a=1

闭包本质是什么?是当前环境中存在指向父级作用域的引用

function fun1() {
  var a = 1;
  var b = 1;
  fun2 = function(){
    console.log(a);
  };
}
fun1();
fun2();

可以看到上面的代码并没有return一个函数,但是依然可以获取到a的值,产生了闭包,声明fun2为全局变量,是因为fun2内部代码用到了fun1也就是父级作用域的变量。是当前环境中存在指向父级作用域(fun1)的引用(fun2)。

第一个用return的案例也用这句话解释一下:当前环境中存在指向父级作用域(fun1)的引用(result)。