闭包的概念

当一个内部函数(嵌套函数)引用了其外部函数的变量,即使外部函数已经执行完毕,这个内部函数仍然可以访问这些外部变量。这种函数和其相关的作用域组合就是闭包。

个人对于概念的简单理解:


想象一下你有一个盒子,里面装着一些东西。这个盒子就是一个函数,而里面的东西就是函数内部的变量。现在,你把这个盒子交给了别人,但是你希望里面的东西不被随便拿走,只有在你允许的情况下才能使用。

举个实际的例子,假设你有一个计数器,你希望其他人可以增加或减少这个计数器的值,但不能直接访问或修改它。你可以使用闭包来创建一个函数,这个函数包含计数器变量,并返回一些可以操作计数器的方法。这样,其他人只能通过这些方法来改变计数器的值,而无法直接访问它。

总之,闭包就像一个保险柜,可以安全地存放你的数据和功能,只有在你允许的情况下才能使用。这种方式使你的代码更加安全和可控。


闭包的一些实例

1.计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function createCounter() {
let count = 0;

function increment() {
count++;
console.log(count);
}

function decrement() {
count--;
console.log(count);
}

return { increment, decrement };
}

const counter = createCounter();
counter.increment(); // 输出 1
counter.increment(); // 输出 2
counter.decrement(); // 输出 1

2.私有变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function createPerson(name) {
let age = 0;

return {
getName: function() {
return name;
},
getAge: function() {
return age;
},
increaseAge: function() {
age++;
}
};
}

const person = createPerson('Alice');
console.log(person.getName()); // 输出 'Alice'
console.log(person.getAge()); // 输出 0
person.increaseAge();
console.log(person.getAge()); // 输出 1

3.模块化编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const myModule = (function() {
let privateData = 'I am private';

function getPrivateData() {
return privateData;
}

function setPrivateData(value) {
privateData = value;
}

return {
get: getPrivateData,
set: setPrivateData
};
})();

console.log(myModule.get()); // 输出 'I am private'
myModule.set('New data');
console.log(myModule.get()); // 输出 'New data'

闭包的生命周期

1.  闭包在外部函数调用时产生,外部函数每次调用都会产生一个全新的闭包(举一个简单的例子便于理解,闭包就像一个资源库,外部函数就相当于这个资源库的钥匙,但是每把钥匙对应一个全新的拷贝资源库`(闭包只能调用,只能让你使用里面的方法,你不可以直接修改里面的方法)`)
1.  在内部函数丢失时销毁(内部函数被垃圾回收了,闭包才会消失)

使用闭包的一个注意事项

​ 闭包主要用来隐藏一些不希望被外部访问的内容(使用闭包要需要占用一定的内存空间)

​ 相较于类来说,闭包比较浪费内存空间(类可以使用原型而闭包不能)

​ 需要执行次数较少时,使用闭包

​ 需要大量创建实例时,使用类