一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
闭包能做的事情,函数也能做,闭包就是一种特殊的函数。
闭包的使用场景:(本质点)
1.当一个嵌套函数内容引用了一个外部函数的变量,就产生了闭包
事件和数组这种都是由于作用域,同步,异步的问题,就是是否已经存储的问题
使用作用域的问题
<div>
<button>第一个</button>
<button>第二个</button>
<button>第三个</button>
</div>
<script>
//使用for循环的函数是否能够拿到实时的内容
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
}
}
a.forEach((data) => {
data();
})
var b = document.getElementsByTagName("button");
for (let i = 0; i < b.length; i++) {
b[i].onclick = function () {
console.log(i + "个")
}
}
</script>
闭包的知识
<script>
//使用for循环的函数是否能够拿到实时的内容
var a = [];
for (var i = 0; i < 10; i++) {
(function (i) {
a[i] = function () {
console.log(i);
}
})(i);
}
a.forEach((data) => {
data();
})
var b = document.getElementsByTagName("button");
for (var i = 0; i < b.length; i++) {
(function (i) {
b[i].onclick = function () {
console.log(i + "个")
}
})(i)
}
</script>
closure闭包(使用chrome调试)
使用闭包做什么用?
1.将函数作为另一个函数的返回值
就是保住大函数中的局部函数的生命周期,那么就将局部函数的函数体做为大函数的返回值,并且使用一个值来接收
<script>
function fn1() {
var sum = 0;
function fn2() {
console.log(sum);
}
return fn2;
}
var f = fn1();
f();
</script>
2.将函数的形参作为实参传 递给另一个函数调用
<script>
function Fn(a, b) {
function fn2(a) {
console.log(a);
}
}
</script>
3.就是刚刚那个局部函数保存生命周期,里面的局部变量也可以保留生命周期,也就是可以封存变量,也就是之前的那个for里面的function和事件,使用闭包的形式,就可以把里面的变量暂时封存,而不是去全局变量中取,使用let增加{}的块级作用域,也就是传一个i就来封存一次。
<script>
function fn1() {
var sum = 1;
function fn2() {
sum++;
console.log(sum);
}
return fn2;
}
var f = fn1();
f();
f();
</script>
4.增加生存周期这个内容,是采用全局变量来封存传回来的局部函数函数体,就是全局变量的指针指向的这个闭包封存局部函数,如果要消除这个内容,就必须要将这个全局变量指针消除指向,那么系统就会将他的赋值变为垃圾内容被清理出去。f=null.
- 闭包中自定义模块封装
在函数中,有些属性不想要外界随意改变,而是一个有规律的改变,那么采用闭包的方式,将规律改变方式闭包函数返回回去。
<script>
//在函数里面的属性,使用闭包的方式让函数里面的属性有规律的改变
function fn() {
var money = 100000000;
function set() {
money--;
return money;
}
function get() {
money++;
return money;
}
return {
"set": set,
"get": get
}
}
var f = fn();
console.log(f.set());
console.log(f.set());
</script>
- 小闭包的方式有很多种
这就是通过闭包的形式封闭的内容,let域推测也是通过闭包的形式,实参和形参也是通过闭包的形式隔离互不影响。
(function(){
console.log("asdf");
})();
- 这儿有个重点,就是window对象这种都是通过这种层层封装闭包的形式,将全局参数传给每一个局部参数里面,只有传入对象才能在局部变量更改,因为引用传递是传递的地址,而值传递直接是在局部变量改变,更改赋值直接更改内存地址,注意注意,就是实参传递形参的内容, 在里面函数也传递参数的话,函数执行就必须带参数,所以实参传递进去,直接引用外面的内容
<button id="btn">点我试试</button>
<script>
function fn(f,time){
function fn2(){
setInterval(f,1000)
}
return fn2
}
var fk=fn(function(){
console.log("sd");
},1000);
fk();
</script>
- 场景应用:
节流:就是点击按钮或者执行这种等等太多,影响性能,通过定时器放慢反应速度,但是你如果不及时处理,会越来越多,占用内存空间多久,容易内存导致泄露,及时释放
-
内存溢出:当程序运行时需要的内存超过剩余的内存时,就会出现内存溢出的情况
-
内存泄露:占用内存没有及时释放,内存泄露没有及时释放就会内存溢出
- 占用内存很大的全局变量
- 没有及时清理的定时器
- 闭包