JS中的闭包详解
文章目录
- JS中的闭包详解
- 一、引言
- 二、闭包的基本概念
- 1、闭包的定义
- 1.1、代码示例
- 2、闭包的实现
- 1.2、代码示例
- 三、闭包的用途
- 1、封装私有变量
- 1.3、代码示例
- 2、做缓存
- 1.4、代码示例
- 3、模块化编程
- 1.5、代码示例
- 4、防抖、节流、函数柯里化
- 1.6、防抖代码示例
- 1.7、节流代码示例
- 四、闭包的缺点
- 五、总结
JS中的闭包详解
一、引言
闭包是JavaScript中的一个核心概念,它允许函数访问其定义时的词法作用域中的变量。这种特性使得闭包在数据封装、回调函数、模块模式等场景中有着广泛的应用。
二、闭包的基本概念
1、闭包的定义
闭包是指有权访问另一个函数作用域的变量的函数。在JavaScript中,闭包可以通过函数嵌套和变量引用实现。
1.1、代码示例
function outerFun() {
let outerVar = '我在outer函数里!';
function innerFun() {
console.log(outerVar);
}
return innerFun;
}
const innerFn = outerFun();
innerFn(); // 输出: 我在outer函数里!
在这个例子中,innerFun
引用了outerVar
,因此JavaScript引擎会保留outerFun
的作用域链,以便innerFun
可以访问outerVar
。
2、闭包的实现
闭包是指一个函数可以访问它定义时所在的词法作用域以及全局作用域中的变量。当内部函数引用外部函数的变量时,外部函数的作用域链将被保留在内存中,以便内部函数可以访问这些变量。
1.2、代码示例
function a() {
var aa = 333;
function b() {
console.log(aa); // 输出:333
}
return b;
}
var demo = a();
demo(); // 输出:333
在这个例子中,b
函数引用了a
函数中的变量aa
,因此即使a
函数执行完毕后,aa
变量仍然可以通过b
函数被访问,形成了闭包。
三、闭包的用途
1、封装私有变量
闭包可以用于封装私有变量,以防止其被外部访问和修改。这可以减少全局变量的数量,降低全局变量被误用或意外修改的风险。
1.3、代码示例
function addFn() {
let count = 1;
function increment() {
count++;
console.log(count);
}
return increment;
}
const counter = addFn();
counter(); // 输出:2
counter(); // 输出:3
在这个例子中,increment
函数通过闭包访问并修改了count
变量,而count
变量不会被外部直接访问。
2、做缓存
闭包可以用于缓存计算结果,减少重复计算。
1.4、代码示例
function fn1() {
var type = 'JavaScript';
let tt1 = 1;
const tt2 = 2;
var innerBar = {
getType: function() {
console.log(tt1);
return type;
},
setType: function(newType) {
type = newType;
}
};
return innerBar;
}
var bar = fn1();
console.log(bar.getType()); // 输出:1 JavaScript
bar.setType('Python');
console.log(bar.getType()); // 输出:1 Python
在这个例子中,getType
和setType
方法通过闭包访问并修改了type
变量。
3、模块化编程
闭包可以用于实现模块化编程,封装模块的私有变量和方法。
1.5、代码示例
const moduleFn = (function() {
let privateVar = '我是私有变量!';
function privateMethod() {
console.log(privateVar);
}
return {
publicMethod: function() {
privateMethod();
}
};
})();
moduleFn.publicMethod(); // 输出:我是私有的!
在这个例子中,privateVar
和privateMethod
被封装在模块内部,只能通过publicMethod
访问。
4、防抖、节流、函数柯里化
闭包在实现防抖、节流和函数柯里化等高级功能时非常有用。
1.6、防抖代码示例
function antishake(fn, wait) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
fn();
}, wait);
};
}
let an = antishake(function() {
console.log('555');
}, 2000);
document.querySelector('div').onmouseenter = () => {
an();
};
1.7、节流代码示例
function throttle(fn, wait) {
let timer = null;
return function() {
if (timer) return;
timer = setTimeout(() => {
fn();
timer = null;
}, wait);
};
}
let throttle1 = throttle(() => {
console.log('我上车了');
}, 2000);
document.querySelector('div').onclick = () => {
throttle1();
};
四、闭包的缺点
闭包可能会导致内存泄漏,因为闭包引用的外部变量不会被垃圾回收。为了避免内存泄漏,可以及时释放闭包或者使用立即执行函数。
五、总结
闭包是JavaScript中一个强大的特性,它允许函数访问其创建时的词法作用域。通过闭包,可以实现数据封装、事件处理、延迟执行等多种高级功能。理解闭包的概念和工作原理对于深入掌握JavaScript至关重要。
版权声明:本博客内容为原创,转载请保留原文链接及作者信息。
参考文章:
- 什么是闭包?以及闭包的作用—JavaScript基础篇 - CSDN博客