目录
- 闭包是什么?
- 闭包怎么用?
- 闭包有什么用?
- 闭包的优缺点是什么?
1.闭包是什么?
闭包:它是一种手段,通过它,内部函数在其父函数结束之后依然可以引用其外围函数中的变量。
我们知道在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有限权访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的,闭包的本质就是在一个函数内部创建另一个函数。
我们首先知道闭包有3个特性:
1. 函数嵌套函数
2. 函数内部可以引用函数外部的参数和变量
3. 参数和变量不会被垃圾回收机制回收
2.闭包怎么用?
- 函数模式的闭包
function f1(){
let age = 22;
function showAge(){
console.log(age);
}
showAge();
};
f1();
- 函数作为返回值使用
function f1() {
let num = 10;
return function () {
return num;
};
};
let ff = f1();
console.log(ff());
在这段代码中,f1()中的返回值是一个匿名函数,这个函数在a()作用域内部,所以它可以获取f1()作用域下变量num的值,将这个值作为返回值赋给全局作用域下的变量ff,实现了在全局变量下获取到局部变量中的变量的值。
- 用闭包产生一个随机数然后输出三次
function showRandom() {
let sr = parseInt(Math.random() * 10 + 1);
//下面用的了ES2015的新特新箭头函数,等效于这段代码
// return function(){
// console.log(sr);
// };
return () => {
console.log(sr);
};
};
let f5 = showRandom();
f5();
f5();
f5();
上面这段代码没什么可说的。
2.对象模式的闭包
function f2(){
let name = "alai";
let obj = {
name
};
console.log(obj.name);
};
f2();
5. 闭包有什么用?
让我们来通过一个典型的例子说明闭包有什么用
图片点赞案例(注意:复制后改图片路径)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0xp;
padding: 0xp;
}
img{
height: 400px;
width: auto;
}
li{
list-style: none;
float: left;
}
</style>
</head>
<body>
<div>
<ul>
<li>
<!-- 这里图面路径要改,自己找几个图片加上去 -->
<img src="Images/11.jpg" alt="">
<input type="button" value="赞(1)">
</li>
<li>
<!-- 同第一个 -->
<img src="Images/22.jpg" alt="">
<input type="button" value="赞(1)">
</li>
<li>
<!-- 同第一个 -->
<img src="Images/33.jpg" alt="">
<input type="button" value="赞(1)">
</li>
<li>
<!-- 同第一个 -->
<img src="Images/44.jpg" alt="">
<input type="button" value="赞(1)">
</li>
</ul>
</div>
<script>
function addZan(){
let value = 2;
return function(){
//下面这句话用到了ES6的模板字符串,不清楚的可以从参考我的另一篇博客
this.value = `赞(${value++})`;//此时的this指向调用的对象,为button
};
};
let objs = document.querySelectorAll("input");
for (let i = 0; i < objs.length; i++) {
objs[i].onclick = addZan();
}
</script>
</body>
</html>
没有什么要提醒的,都是极其简单的代码。有不清楚的私信你我。
4. 闭包的优缺点是什么?
最后总结一下闭包的好处与坏处
优点:
-
保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突。
-
在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)。
-
匿名自执行函数可以减少内存消耗。
缺点:
-
优先就是缺点,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
-
其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。