闭包
之前总是知道闭包,却没有充分的理解闭包,今天就好好梳理一下闭包的作用和一些弊端。
先来看看MDN闭包的定义
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。
打重点:内部函数访问外部函数的作用域
举一个栗子:他的作用就好比,你有100圆子(内部函数),你想要买一个东西需要花200圆子,你通过某种方式(访问外部函数的作用域)将100圆子变成了200
function getMoreMoney(multiple){
const myMoney =100
return function (){
return myMoney*multiple
}
}
闭包的作用
1)缓存状态:闭包可以保持函数执行时的上下文状态,使得函数可以记住之前的操作或状态
function Counting(){
let count= 1
return {
add:function(){
console.log(++count)
},
reduce:function(){
console.log(--count)
},
getValue:function(){
return count
}
}
}
const state = Counting()
state.add() //2
state.add() //3
state.reduce() //2
2)封装变量:闭包可以将变量和函数封装在一个作用域内,避免全局命名冲突,并提供私有性,使得变量和函数对外部不可见
function createCounter() {
let count = 0
return function() {
count++
console.log(count)
};
}
const counter = createCounter();
counter() // 输出: 1
counter() // 输出: 2
3)函数工厂:闭包可以用于生成定制的函数,根据不同的配置参数返回不同的函数
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 输出: 10
const triple = createMultiplier(3);
console.log(triple(5)); // 输出: 15
坑
不正当的使用闭包可能会造成内存泄漏
1)内存泄漏:由于闭包会保持对外部变量的引用,如果闭包长时间存在,并且引用的外部变量占用大量内存,就可能导致内存泄漏
function createLeak() {
const bigArray = new Array(1000000).fill(0);
return function() {
console.log(bigArray[0]);
};
}
const leakFunc = createLeak();
leakFunc(); // 每次调用都会访问大数组的第一个元素,可能导致内存泄漏
闭包函数中引用的外部变量会被保存在内存中,即使函数执行完毕,这些变量也不会被释放。如果闭包函数长时间存在,并且引用的外部变量占用大量内存,就会导致内存泄漏。
为避免闭包造成内存泄漏,在不再需要使用闭包时,确保将其置为 null 或者解除所有对闭包函数的引用,以便让垃圾回收机制回收相关资源(这个过程叫做GC)
function createLeak() {
const bigArray = new Array(1000000).fill(0);
return function() {
console.log(bigArray[0]);
};
}
const leakFunc = createLeak();
leakFunc(); // 每次调用都会访问大数组的第一个元素,可能导致内存泄漏
leakFunc = null //手动置空,避免内存泄漏