「JS」闭包


闭包是指有权访问另外一个函数作用域的变量的函数。——《JavaScript 高级程序设计》

闭包的特点首先是函数,其次是它可以访问到父级作用域的变量对象,即使父级函数完成调用后”理应出栈销毁“。

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

教程:前端进击的巨人(三):从作用域走进闭包

创建闭包的常见方式,就是在一个函数内部创建另一个函数。
一般闭包的出现:

  • 函数作为参数传递
  • 函数作为返回值传递
function foo() {
  var fooVal = "2019";
  var bar = function () {
    console.log(fooVal); // bar中使用到了自由变量fooVal
  };
  return bar; // 函数作为参数返回
}

var getValue = foo();
getValue(); // 2019

通过闭包,我们在外部环境也可以获取到变量fooVal,虽然foo()函数执行完成了,但它并没从函数调用栈中销毁,其变量对象存储仍然可以通过getValue()能被访问到。
**bar**之所以还能够访问这个变量,是因为内部函数的作用域链中包含foo()的作用域。

为什么foo执行完成没有出栈?

当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。然后,使用 arguments 和其他命名参数的值来初始化函数的活动对象(activation object)。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,……直至作为作用域链终点的全局执行环境。

function compare(value1, value2) {
  if (value1 < value2) {
    return -1;
  } else if (value1 > value2) {
    return 1;
  } else {
    return 0;
  }
}
var result = compare(5, 10);

全局环境内有 compare 和 result 两个变量对象。
截屏2020-10-19 上午10.13.38.png
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多。

function createFunctions() {
  var result = new Array();
  for (var i = 0; i < 10; i++) {
    result[i] = function () {
      return i;
    };
  }
  return result;
}

每个匿名函数的作用域链中都保存着 createFunctions() 函数的活动对象,所以它们引用的都是同一个变量 i 。 当 createFunctions()函数返回后,变量 i 的值是 10,此时每个函数都引用着保存变量 i 的同一个变量对象,所以在每个函数内部 i 的值都是 10。
通过创建另一个匿名函数:
÷


文章作者: 阿汪同学
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿汪同学 !
评论
  目录