学JavaScript有段时间了,遇到闭包问题有时还是会犯错,最近在整理笔记,也以此来加深理解。
这部分之所以会放在一起整理,是因为匿名函数和闭包的概念很容易混淆,经常会用错。
闭包作为JavaScript的一个难点,也是它的一个特色,很多高级应用都要通过闭包实现,正确的理解和使用闭包是很重要的。闭包是建立在匿名函数之上的,所以先要正确了解匿名函数。
- 匿名函数
先看一个普通函数的例子:
function f1() { //函数名是 f1
return 'f1()';}
这个函数如果匿名会是:
function () { //匿名函数,会报错
return 'noname';}
匿名函数赋值:
var f1 = function () { //将匿名函数赋给变量
return 'f1';
};
alert(f1()); //调用方式和函数调用相似
函数里的匿名函数:
function box () {
return function () { //函数里的匿名函数,产生闭包
return 'Lee';
}
}
alert(box()()); //调用匿名函数
- 闭包
简单来讲,闭包就是能够读取其他函数内部变量的函数。
闭包是指有权访问另一个函数作用域中的变量的函数, 创建闭包的常见的方式, 就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
写一个通过闭包返回局部变量的例子:
function f1() {
var user = 'Lee';
return function () { //通过匿名函数返回 f1()局部变量
return user;
};
}
alert(f1()()); //通过f1()()来直接调用匿名函数返回值
var f= f1();
alert(f()); //另一种调用匿名函数返回值
- 闭包的用途
例如:通过匿名函数实现累加
var age = 100;
return function () {
age ++;
return age;
}
}
var b = box(); //获得函数
alert(b()); //调用匿名函数
alert(b()); //第二次调用匿名函数,实现累加
- 使用闭包的注意点
1)使用闭包有一个优点,也是它的缺点:就是可以把局部变量驻留在内存中,可以避免使用全局变量。同时,由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。PS:如果并没有使用解除引用,那么需要等到浏览器关闭才得以释放。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
3)在闭包中使用 this 对象也可能会导致一些问题,this 对象是在运行时基于函数的执行环境绑定的,如果 this 在全局范围就是 window,如果在对象内部就指向这个对象。而闭包却在运行时指向 window 的,因为闭包并不属于这个对象的属性或方法。