1. 什么是闭包
应用MDN文档来说:函数和对其周围状态(词法环境,lexical environment)的引用共同构成了闭包。也就是说,闭包可以让你在一个内层函数种访问到其外层函数的作用域。
如下代码就是一个闭包。
let x = 1
function f(){
console.log(x)
}
2. 闭包的用途
-
从外部读取局部变量
function f1(){ let n = 222 function f2(){ console.log(n) } return f2 } let result = f1() result() //222上面代码中,函数
f1的返回值是函数f2,由于f2可以读取f1内部变量,所以可以在外部获得f1的内部变量了。 -
让读取到变量的值始终保存在内存中
function f1(){ let n = 222 function f2(){ console.log(++n) } return f2 } let result = f1() result() //223 result() //224 result() //225如上代码中,函数
f1中的局部变量n一直保存在内存中,并没有在f1调用后被删除。原因在于f1是f2的父函数,f2被赋值给了一个全局变量,这使得f2一直存在在内存中,而f2的存在依赖于f1,所以f1也一直存在内存中,不会被垃圾回收机制回收。所以,闭包也可以理解为能够读取其他函数内部的函数。
-
用闭包封装对象的私有属性和私有方法
function Person(name){ let $age function setAge(n){ $age = n } function getAge(){ return $age } return { name: name, getAge: getAge, setAge: setAge } } let p1 = Person('张三') p1.setAge(26) p1.getAge() //26
上面代码中,函数 Person 的内部变量 $age,通过闭包 getAge 和 setAge,变成了返回对象 p1 的私有变量。
3. 闭包的优缺点
优点: 可以避免全局变量的污染。
缺点:
-
由于闭包会使得函数中的变量都被保存到内存中,内存消耗会很大。所以不能滥用闭包,否则会造成网页的性能问题,在 IE 中可能导致内存泄漏(解决方法是,推出函数前,将不适用的局部变量全部删除)。
-
闭包会在父函数外部,改变父函数内部变量的值。所以,在把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性时,一定不要随意改变父函数内部变量的值。