问:什么是闭包?
答:闭包就是能够读取其他函数内部变量的函数。
问:闭包的用途是什么?
答:闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。闭包的另一个用处,是封装对象的私有属性和私有方法。
问:闭包的缺点是什么?
答:外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。
什么是闭包解释:
JavaScript 有两种作用域:全局作用域和函数作用域。
函数内部可以直接读取全局变量。
函数外部无法读取函数内部声明的变量。
在一般情况下,函数外部无法读取函数内部声明的变量,下面代码中,函数f1内部声明的变量n,函数外是无法读取的。
function f1() {
var n = 999;
}
console.log(n)
但是我们可在函数内多添加一个函数,并返回这个函数,就可读取函数内部的变量了。
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 999
上面代码中,在函数f1内部又增加了一个函数f2,将函数f2设置为函数f1的返回值,由于f2可以读取f1的内部变量,所以通过返回f2就可以在外部获得f1的内部变量了,这就是典型的闭包。
闭包的用途解释:
-
读取函数内部的变量已在上文解释完毕
-
让变量始终保持在内存中
function createIncrementor(start) {
return function () {
return start++;
};
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7
上面代码中,start是函数createIncrementor的内部变量。通过闭包,start的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包inc使得函数createIncrementor的内部环境,一直存在。所以,闭包可以看作是函数内部作用域的一个接口。
- 封装对象的私有属性和私有方法
function Person(name) {
var _age;
function setAge(n) {
_age = n;
}
function getAge() {
return _age;
}
return {
name: name,
getAge: getAge,
setAge: setAge
};
}
var p1 = Person('张三');
p1.setAge(25);
p1.getAge() // 25
上面代码中,函数Person的内部变量_age,通过闭包getAge和setAge,变成了返回对象p1的私有变量。