示例:

function foo() {
  var name = "foo";
  var age = 18;
  function bar() {
    console.log("bar", name);
  }
  return bar;
}
var fn = foo();
fn();
// bar foo案例中定义了一个函数foo,并且将foo返回值bar赋值给了fn,执行fn函数。发现仍然可以打印出来name,按理说在 *var fn = foo(); 时,foo函数的调用栈就已经被销毁,怎么在执行fn函数时还能够访问的到呢?这就形成了闭包。

内存分析:

当执行完foo函数,GO对象中的fn指向foo函数中的bar函数对象,因为bar函数对象的父级作用域指向foo函数的AO对象,所以foo函数中的变量name并不会被销毁。这样当fn函数执行了一次,foo的AO对象和bar函数对象不会被销毁,就会产生内存泄漏。可以手动指定 fn = null 来销毁。

定义:

  • 闭包在实现上是一个结构体,它存储了一个函数和一个关联的环境。闭包跟函数最大的区别在于,当捕捉闭包的时候,它的自由变量会在捕捉时确定,这样即使脱离了捕捉时的上下文,它也能照常运行。
  • 闭包是两部分组成:函数+可以访问的自由变量

用途:

  • 1,从外部读取函数内部的变量。上述示例中可以访问打印name
  • 2,将创建的变量的值始终保持在内存中,上述示例会导致内存泄漏,使name始终存在于内存中
  • 3,封装对象的私有属性和私有方法