💂 个人网站: 【紫陌】【笔记分享网】
💅 想寻找共同学习交流、共同成长的伙伴, 请点击【前端学习交流群】
1. 对闭包的理解
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。
简单的例子:
function fn() {
var num = 100; //fn函数作用域内部的变量
function fun() {
console.log(num); //fun函数可以访问fn函数变量
}
fun();
}
fn();
//可以简写成
function fn() {
var num = 100; //fn函数作用域内部的变量
return function() { //直接return匿名函数
console.log(num); //fun函数可以访问fn函数变量
}
}
let f = fn()
f()
//类似于
// let f = function() {
// console.log(num);
// }
2.闭包的原理
作用域链,当前作用域可以访问上级作用域中的变量,闭包也可以说一种现象。
3.闭包的用途
- 访问函数内部的变量
- 防止函数内部的变量执行完城后,被销毁,使其一直保存在内存中。
4.闭包的优点缺点
- 优点:可以延伸变量的 作用范围
- 缺点:由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出。所以使用完闭包后,可以通过手动对闭包 f = null(看下面代码) ,让垃圾回收器回收
内存泄漏的解决方法:
function fn() {
var num = 100;
return function (){
console.log(num++); //每次调用加一
}
}
let f = fn()
f() //100
f() //101
f() //102
f = null // 手动释放fn()的引用
var f1 = fn() // fn()的引用f()被释放了,现在fn()的作用域也被释放了。fn()再次归零了。
f1() //100
5. 闭包的应用场景
- 采用函数引用方式的setTimeout调用。
- 将函数关联到对象的实例方法。
- 给对象设置私有变量并且利用特权方法去访问私有属性
- 防抖节流函数
- Vue中数据响应式Observer中使用闭包等。
案例:
需求:点击li输出当前li的索引号
<body>
<ul class="nav">
<li>吃饭</li>
<li>睡觉</li>
<li>打游戏</li>
<li>打豆豆</li>
</ul>
<script>
// 1. 我们可以利用动态添加属性的方式
var lis = document.querySelector('.nav').querySelectorAll('li');
// 2. 利用闭包的方式得到当前小li 的索引号
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
// console.log(i);
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
</script>
</body>
需求:3秒钟之后,打印所有li元素的内容
<body>
<ul class="nav">
<li>吃饭</li>
<li>睡觉</li>
<li>打游戏</li>
<li>打豆豆</li>
</ul>
<script>
// 闭包应用-3秒钟之后,打印所有li元素的内容
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
</script>
</body>
看完点赞!!!