示例:
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,封装对象的私有属性和私有方法
function f1(n) {
return function () {
return n++;
};
}
var a1 = f1(1);
a1() // 1
a1() // 2
a1() // 3
var a2 = f1(5);
a2() // 5
a2() // 6
a2() // 7
//这段代码中,a1 和 a2 是相互独立的,各自返回自己的私有变量。