JS知识点小结1

84 阅读2分钟

什么是闭包?闭包的用途是什么?闭包的缺点是什么?

什么是闭包

想了解闭包,必须先理解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的问题。