一.什么是闭包?
我看看了很多的解释,看的人云里雾里的。最后总结了一下,闭包其实就代码编写时呈现的一种特定形式,就是在一个函数中定义并返回了另外一个函数,在这个内部定义的函数中可以访问外面的函数定义的变量,但是外面函数不能访问内部函数定义的变量。
function test1(){
var a = "abc";
var b = "efg";
var test2 = function(a1,b1){
console.log("a1:"+a1+"--b1:"+b1);
}
return test2(a,b);
}
闭包其实和js的作用域是紧紧相关联的,要想了解闭包还必须首先了解一下js的作用域。
这里我们先不考虑ES6,我们只考虑ES5及以下。
作用域?
作用域其实就是变量或或属性能够起作用的范围,就像我们常说的领空一样,我们国家的战斗机一般只能在我们自己的领空进行巡逻,训练啥的,你如果跑到其他国家的领空去了你这就叫入侵了,这是要出事情的,轻者就像我们外交部常说那样“我们抗议,我们严重抗议,我们坚决反对”然后没了;重者就像土耳其直接将俄罗是的战机干下来一样。当然美帝是一个Bug,不考虑。言归正传,js的作用域分为局部作用域和全局作用域。
局部作用域又叫函数作用域,他只在函数内部生效,定义在该作用域内的变量或属性,就只能在该函数内可以访问。其他的函数想访问,对不起,此领空不开放。
var age="10";
function person(){
var name = "wang_yangyang";
}
上面代码中person函数在执行的时候就形成了一个局部作用域,在该作用域中name就是局部变量只有在person中才能访问到,你在person外面是访问不到的。另外就是全局作用域了,顾名思义就是在哪里都可以访问的,由一种普天之下莫非王土的赶脚。
类似上面代码中age说在的作用域就是全局作用域,你在所有全局作用域定义的函数中都可以访问
二.闭包有什么用?
其实概括起来说闭包主要有两个用处:
1.内存常驻:
我们知道js的垃圾回收机制(GC)是自动回收(标记清除,标记计数),这个我们后面再讲。所谓自动回收就是在程序在运行完后申明的变量就从内存中释放掉了,这是再访问该变量可能就访问不到了,或者说不是你要的结果了,比如:
var a = [];
for(var i = 0 ;i<10;i++){
a[i] = function(){
console.log(i)
};
}
a[1](); //10
a[2](); //10
你会发现无论怎样输出结果但是10,并没有达到我们想要的效果,那这是这是什么原因呢?这是因为当我们执行ai的时候上一次的程序已经执行完了,这个时候i在全局作用域中已经变成了10,当你再执行啊ai时,console.log(i)自然全部就是10了。那要怎么样才能达到我们的目的呢,这个时候其实使用闭包就相当简单了;
var a = [];
for(var i = 0 ;i<10;i++) {
a[i] = function(i){
return function(){
console.log(i);
}
}(i)
};
a[1]()
a[1](); //1
a[2](); //2
上面的代码就够成个一个闭包,这样啊闭包总的变量就会一直在内存中存在,不会被回收,也达到了我们的目的。
2.隔离作用域
我们知道如果我们的项目如果很大的话就必然会使用到很多的变量,如果这些变量管理不好就会造成变量污染,这个时候进行作用域隔离就是必须的了。闭包有一个明显的特征就是可以访问外面的变量,但是外面的变量无法访问内部函数的变量。我们利用这个特征就可以实现作用域隔离。集体实现我们可以参考一下jQuery的实现。大概就是:
(function(window,undefined){
var jQuery = function(){
};
window.jQuery = window.$ = jQuery();
})(window,undefined)
上面的代码形成了一个匿名函数自执行,其实就是一个闭包,我们将window变量和undefined作为参数传进去,然后再将要暴露的属性通过window这个对象作为桥梁暴露到全局作用域中。这样无论你在上面的代码中申明多少变量,只要你没有通过window对象暴露出去,这些申明的变量就永远不会污染到全局变量。建议有一定基础的可以去看看jQuery 的源码,其实它里面的很多实现是非常巧妙的,对我们的js编程提高有很好的效果。
这只是主要的两个用处,闭包还有许多用处,比如在申明自定义对象的时候可以使用,具体情况具体分析,做到活学活用,程序是死的,人是活的。
三.使用闭包需要注意什么?
我们可能会觉得既然闭包这个好那我们能不能大量使用呢!答案是,可以使用,但是不要大量使用,更不可乱用,因为我们知道闭包中的变量是不会被回收的,这样随着变量数量的增加,内存的消耗也会不断的变大,最后有可能出现内存泄漏,导致页面假死,浏览器崩溃等问题。
四、那你知道什么情况下会用到闭包吗
项目中定时器
五闭包的优点和缺点:https://blog.csdn.net/weixin_43955769/article/details/90521768
优点
它的最大用处有两个,一个是它可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
① 减少全局变量;
② 减少传递函数的参数量;
③ 封装;
缺点:
① 使用闭包会占有内存资源,过多的使用闭包会导致内存溢出等
面试官:正好你提到了内存泄漏,说说你的解决方法
应聘者:简单的说就是把那些不需要的变量,但是垃圾回收又收不走的的那些赋值为null,然后让垃圾回收走