什么是闭包?闭包的用途是什么?闭包的缺点是什么?
什么是闭包
想了解闭包,必须先理解JavaScript中函数是存在作用域的。作用域是在运行时代码中的特定部分中可访问的变量,函数和对象的集合。作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
回到闭包这个概念,非常概要的说一个持有外部环境变量的函数就是闭包。一个函数有权访问外部作用域中的变量,那么它和它所访问的外部变量,就一起构成了一个闭包。 举一个简单的例子:
function f1() {
let a = 'jack';
let f2 = function() {
console.log(a);
}
}
这里的f2就是一个闭包函数,因为他能够访问到外部函数f1的作用域中的变量。所以函数的作用域其实是对外封闭的,f1内部的所有局部变量,对f2都是可见的;但是反过来就不行,f2内部的局部变量,对f1就是不可见的。
闭包的用途
本质上,闭包就是将函数内部和函数外部连接起来的桥梁。它的最大用途有两个,一个是可以读取函数内部的变量,另一个就是让形成闭包的变量的值始终保持在内存中,不会在外部函数f1调用后被自动清除。 首先,还是用上面的例子稍加修改说明闭包如何读取函数内部的变量:
function f1() {
let a = 'jack';
let f2 = function() {
console.log(a);
}
return f2;
}
let output = f1();
output(); // 输出'jack'
通过return返回f2,调用了f1中的闭包函数f2,就可以在外部读取f1内的变量a了。
用途2是,将创建的变量的值始终保持在内存中:
function f1() {
let n = 1;
let f2 = function() {
n++;
console.log(n);
}
return f2;
}
let output = f1();
output(); // 输出2
output(); // 输出3
output(); // 输出4
可以看到,n可以持续累加,函数f1中的局部变量n通过闭包一直保存在内存中,并没有在f1调用后被自动清除。
闭包的缺点
闭包的这些特点,也导致它存在弊端。首先,由于闭包会使得闭包中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页性能问题,还可能导致内存泄露。解决方法是,在退出函数之前,需要主动释放不使用的局部变量。
还有个问题是,闭包函数内的this指向问题:
let object = {
name: 'jack',
getName: function() {
return function() {
console.info(this.name)
}
}
}
object.getName()() // 输出underfined
getName因为内部又包了一层函数,形成闭包后,闭包函数是在window作用域下执行的,也就是说,this指向windows而不再是对象object。使用闭包时需要注意this的问题。