function f1() {
var n = 1;
function f2() {
console.log(n); // 1
}
}
函数f2
就在函数f1
内部,这时f1
内部的所有局部变量,对f2
都是可见的。但是反过来就不行。父对象的所有变量,对子对象都是可见的,反之则不成立。but只要把f2
作为返回值,我们就可以在f1
外部读取它的内部变量了。
function f1() {
var n = 1;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 1
函数f1
的返回值就是函数f2
,由于f2
可以读取f1
的内部变量,所以就可以在外部获得f1
的内部变量了。闭包就是函数f2
,即能够读取其他函数内部变量的函数。由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2
记住了它诞生的环境f1
,所以从f2
可以得到f1
的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
作用:①可以读取外层函数内部的变量。②让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。
下面的例子,闭包使得内部变量记住上一次调用时的运算结果。
function createAdd(num) {
return function () {
return num++;
};
}
var innerFun= createAdd(5);
innerFun() // 5
innerFun() // 6
innerFun() // 7
上面代码中,num
是函数createAdd
的内部变量。通过闭包,num
的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包inc
使得函数createAdd
的内部环境一直存在。所以,闭包可以看作是函数内部作用域的一个接口。
为什么闭包能够返回外层函数的内部变量?原因是闭包(上例的innerFun
)用到了外层变量(num
),导致外层函数(createAdd
)不能从内存释放。只要闭包没有被垃圾回收机制清除,外层函数提供的运行环境也不会被清除,它的内部变量就始终保存着当前值,供闭包读取。
function Person(name) {
var age;
function setAge(n) {
age = n;
}
function getAge() {
return age;
}
return {
name,
getAge,
setAge,
};
}
var p1 = Person('潇洒');
p1.setAge(18);
p1.getAge() //18
上面代码中,函数Person
的内部变量age
,通过闭包getAge
和setAge
,变成了返回对象p1
的私有变量。
阮一峰的js很不错,推荐大家看。