闭包的用途及缺点是什么?
闭包:如果一个函数用到了它作用域外面的变量,那么这个变量和这个函数之间的环境就是闭包
例1:
<script type="text/javascript">
let a = 5;
function fn(){
a++;
console.log(a);
}
fn();//6
fn();//7
</script>
**闭包的用途:闭包可以用在许多地方。它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会被自动清除(如例1).**下面介绍几种:
1.模仿块级作用域:
所谓块级作用域就是指在循环中定义的变量,一旦循环结束,变量也随之销毁,它的作用范围只在这一小块。而在JavaScript中没有这样的块级作用域,由于JavaScript不会告诉你变量是否已经被声明,所以容易造成命名冲突,如果在全局环境定义的变量,就会污染全局环境,因此可以利用闭包的特性来模仿块级作用域。
在下面的代码中,闭包就是那个匿名函数,这个闭包可以当函数X内部的活动变量,又能保证自己内部的变量在自执行后直接销毁。这种写法经常用在全局环境中,可以避免添加太多全局变量和全局函数,特别是多人合作开发的时候,可以减少因此产生的命名冲突等,避免污染全局环境
例2:
<script type="text/javascript">
function fn(num){
(
function (){
for(let i=0;i<5;i++){
num +=num
}
}
).call();//声明一个函数立即调用以后,浏览器刷新页面会报错,可以用一个小括号把整段函数包起来。
console.log(num);
}
fn(5)//160
</script>
2.可以读取或储存函数内部的变量:
保存外部函数的变量,内部函数保留了对外部函数的活动变量的引用,所以变量不会被释放。
这种写法可以用在把一些不经常变动计算起来又比较复杂的值保存起来,节省每次的访问时间。
例3:
<script type="text/javascript">
function fn() {
var a = 1;
return {
function() {
return a
}
}
}
let d = fn()
</script>
3.封装私有变量:
我们可以把函数当作一个范围,函数内部的变量就是私有变量,在外部无法引用,但是我们可以通过闭包的特点来访问私有变量。
例4:
<script type="text/javascript">
let person = function(){
//变量作用域为函数内部,外部无法访问
let name = "default ";
return {
getName() {
return name;
},
setName(newName) {
name = newName;
}
};
}();
console.log(person.name);//undefined
console.log(person.getName());//default
person.setName('jack');
console.log(person.getName());//jack
</script>
闭包的缺点:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。