闭包是指有权访问另一个函数作用域中的变量的函数。或简单理解为定义在一个函数内部的函数,该内部函数持有外部函数内变量的引用,即使它在创造它的环境之外执行。 例如:在函数f1 的内 部 ,?定 义 一 个 函 数 f2(闭包),它可以读取f1中的变量。然后只要把f2作为返回值,就可以在f1外读取f1内部变量。
function f1(){
n = 999;
function f2(){ //f2是一个闭包
alert(n);
}
return f2;
}
var result = f1();
result(); //999
f1是f2的父函数,f2被赋给了一个全局变量,始终存在于内存中,而f2的存在依赖f1因此f1也始终 存在内存中 ,不会在调用结束后,被垃圾回收机制回收。
深入原理:当一个函数执行时会创建一个执行环境(含有一个该环境所有变量的变量对象)及相应的作用域链。
作用域链是一个指针列表,前端指向该函数环境的变量对象,第二位是其包含函数环境的变量对象,依次向外直到全局环境 的全局对象。函数在执行中需要访问某个变量时就会顺着作用域链查找。
f2的作用域链包含了 f2,f1及全局的变量, f2因此可以访问到f1中的变量。
一般情况下f1执行完毕环境和变量对象就会销毁,但是由于返回的f2的作用域链仍在引用f1的变量对象,所以f1中变量仍留在内存中。
除非用f2=null解除f2的引用,垃圾回收机制会将其销毁(伴随作用域链),fl也会安全销毁。
由于闭包会使其所有外部环境的变量对象都被保存在内存中,可能会造成内存泄漏。
应用:可以隐藏变量使其无法直接访问, 需通过函数间接访问。可以让变量长期驻 留在内存中,以供其他地方访问。模块是 闭包最强大的一个应用。
可以隐藏变量使其无法直接访问, 需通过函数间接访问。可以让变量长期驻 留在内存中,以供其他地方访问。模块是闭包最强大的一个应用。
function module() {
var a = 10;
var b = 20;
function fn1() {
console.log(a);
}
function fn2() {
console.log(b);
}
return {
fn1: fn1,
fn2: fn2
}
}
var foo = module();
foo.fn1(); //10
foo.fn2(); //20
//fn1, fn2是模块对外暴露的公共方法。变量a, b则为私有变量。
cs