什么是闭包 --- 闭包的概念 (一个不能被回收释放的栈空间,叫闭包)
-
1、在 JS 忍者秘籍(P90)中对闭包的定义:闭包允许函数访问并操作函数外部的变量。
-
2、红宝书上对于闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数。
-
3、MDN 对闭包的定义为:闭包是指那些能够访问自由变量的函数。这里的自由变量是外部函数作用域中的变量。
总结: 闭包是指有权访问另一个函数作用域中变量的函数
基本实现
function makeFunc() {
const name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
const myFunc = makeFunc();
myFunc();
从底层看闭包
闭包的作用
闭包的作用主要有这几点
- 收敛权限
- 封装变量
- 防止变量被污染
// 不使用闭包进行记数
// let count = 1
// function fun(){
// count++
// console.log(`函数被调用${count}次`);
// }
// fun() // 1
// fun() // 2
// // 如果我进行了修改,那么这个数据将会被污染
// count = 1000
// fun() // 1001
// count 是全局变量,容易被修改,采用闭包形式就不会出现这种情况
// 闭包
function closer() {
let count = 0
function fn() {
count ++
console.log(`函数被调用${count}次`);
}
return fn
}
let fn = closer()
fn()
count = 1000 // 私有变量无法修改
闭包的应用:实现数据的私有,不会被外部修改
性能考量
会导致内存泄漏
在JavaScript中,闭包会对性能产生影响,特别是在循环中创建闭包时。闭包会保留对其外部变量的引用,这可能导致内存泄漏。例如,在循环中创建闭包可能会导致每次迭代都创建一个新的闭包,从而导致额外的内存占用,特别是在IE8及以下版本中,其垃圾收集器无法清理这些闭包所引用的变量。
解决方法:
避免在循环中创建闭包。
如果需要在循环中使用外部变量,可以将变量的值在循环中保存到局部变量中。
示例代码:
// 不好的示例 - 在循环中创建闭包
for (var i = 0; i < someArray.length; i++) {
someArray[i].onClick = function() {
alert(i); // 引用外部变量i
};
}
// 更好的做法 - 将循环中的变量值保存到局部变量中
for (var i = 0; i < someArray.length; i++) {
var localIndex = i; // 将变量值保存到局部作用域
someArray[i].onClick = function() {
alert(localIndex); // 使用局部变量
};
}
在这个示例中,第一种方法会创建多个闭包,每个闭包都引用外部的i变量,而最后一种方法通过将i的当前值赋给局部变量localIndex,从而避免了闭包引用外部变量的问题。