持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
闭包这个东西,我们可能最开始并不是很熟悉,但是我们一定使用过闭包!
比如:
function Person(name) {
this.name = name;
let category = 'person';
this.show = function() {
console.log(`我的种类是${category},我的名字是${name}`);
}
}
let ly = new Person('ly');
ly.show() //我的种类是person,我的名字是ly
什么是闭包?
虽然我们使用过闭包,但是什么是闭包呢?
闭包指的是那些引用了另一个函数作用域中变量的函数。
所以要搞懂闭包就得搞懂什么是作用域? 之前我总结过什么是全局作用域,什么是局部作用域以及作用域链,总结过来我感觉全局作用域就是在最外层的全局上下文中定义的变量,而局部作用域主要就是定义在函数内部的变量(还有定义在块级当中的,但是有些定义方式在块级作用域中定义的还是会属于全局作用域,比如var)。
所以,我们只要在一个函数中使用了另一个函数作用域中的变量后,也就使用了闭包。
闭包的作用?
闭包可以延长我们函数作用域中变量的生存周期。因为我们的函数在使用完毕后,就会被清理掉,里面的变量也就不复存在了,哪怕我们再次调用这个函数,这个函数只会新开辟一个内存空间,重新进行变量的赋值。就好比我们打一把英雄联盟,这把游戏结束了,你再重新开一把排位,又是从1级300金币开始,你上次的18级6神装就没有了。
function add() {
let a = 1;
console.log(a++);
}
add(); //1
add(); //1
如果我们想让上面的例子中的a可以保存下来,下次调用时不用从1开始加,我们就需要使用闭包。
function add() {
let a = 1;
return function() {
a++;
console.log(a);
}
}
let newAdd = add();
newAdd(); // 2
newAdd(); // 3
这是因为我们返回了一个函数,这个函数引用了外层函数add的作用域,那么当这个add()执行完毕后,作用域不会被清理,垃圾回收机制不会对add的内存进行回收,而不使用闭包,当add()执行完毕后,add的作用域被清理,内存被回收,a也就不复存在了。
其实我们在平时的使用中,大量使用了闭包,因为很多回调函数都会使用外部函数的变量,这就形成了闭包。
闭包的缺点
我们之前也说了,浏览器的内存是有限的,如果我们使用内存过多而没有清理,那么我们页面的性能也就会变得很差,而使用闭包,就会造成该清楚的内存没有被清除,从而导致内存过大。这就造成了内存泄漏,所以我们还是要尽量少使用闭包。