# 闭包

闭包也算是js绕不过去的一个议题了。

# 概念

闭包是指那些能够访问自由变量的函数

那么什么是自由变量呢?

自由变量是指在函数中使用的, 但是既不是函数参数也不是函数的局部变量的变量。

所以

闭包 = 函数 + 函数能够访问的自由变量

来个例子

let a = 1;
function foo() {
  console.log(a);
}

函数foo + 变量a组成了一个闭包。从技术的角度讲,函数就是一个闭包。

ECMAScript中,闭包指的是:

  1. 从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
  2. 从实践角度:以下函数才算是闭包:
    1. 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)
    2. 在代码中引用了自由变量

举几个面试题的例子吧

var scope = 'global scope';
function checkscope() {
  var scope = 'local scope';
  function f() {
    return scope;
  }
  return f;
}

var foo = checkscope();
console.log(foo()); // local scope

函数foo的作用域链上维护了checkscope函数的活动对象, 虽然checkscope已经执行完出栈了, 但是他的局部变量scope还保存在foo的作用域链上,(造成了内存泄漏)。这段demo满足从实践角度来解释闭包。

必刷题

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0]();
data[1]();
data[2]();

答案都是3,此时也是闭包,只不过外部自由变量i变成了3. 所以都打印3.

稍作修改变成打印 0 1 2.

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = (function (i) {
    return function () {
      console.log(i);
    };
  })(i);
}

data[0]();
data[1]();
data[2]();

更加详细的还是看下面的链接吧。从作用域链和活动对象来分析, 更加的合理。

闭包 (opens new window)

上次更新: 1/22/2025, 9:39:13 AM