Skip to content

函数外面通常拿不到里面的局部变量。变通办法是:在函数里再定义一个函数,把它 return 出去。里面那个函数就是闭包。

javascript
function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

f2 在 f1 内部,能看见 f1 的局部变量;反过来不行。这是作用域链:内层能向外找,外层不能向内找。把 f2 返回到外面,就等于留了一座桥,专门用来读(或改)那批本来出不去的变量。

变量会留在内存里 ​

javascript
function f1() {
  var n = 999;
  nAdd = function () {
    n += 1;
  };
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999
nAdd();
result(); // 1000

result 实际是 f2。调两次,n 从 999 变成 1000,说明 f1 结束之后 n 没有被回收。f2 还被外面握着,它又依赖 f1 的环境,于是那份环境一直活着。

注意 nAdd 前面没有 var / let / const,它漏成了全局变量,本身也是闭包,相当于给 n 做了一个外部的 setter。现在更稳妥的写法是不要这样漏全局,把增减也 return 出去,或放在一个返回的对象上。

可以记:闭包能读到外层函数的局部变量,并让它们按需要活着。这也是它容易把内存咬住的原因——外面还握着内层函数,外层的变量就扔不掉。

测试开发工程师 · 专注自动化与系统架构 | 邮箱: hansblog@atumsoul.win