一、闭包概念闭包:一个函数可以访问另一个函数作用域内的变量;一般情况是在一个函数中包含另一个函数。从官方定义我们知道闭包是一个函数,但是这个函数有【超能力】,可以访问另一个函数的作用域。为什么这叫做【超能力】?因为我们知道函数作用域是独立封闭的,外部执行环境是访问不到的,但是闭包有这个能力和权限。闭包是一种什么样的表达方式?首先,闭包是一个函数,存在于另一个函数中。二、闭包可以访问父函数的变量,变量不会破坏//per的值是return后的结果,即catfunctionper();//YesFishper()等同于cat()per();//游鱼同上,变量name没有被销毁,一直保存在内存中,供函数cat调用per();//游鱼2.闭包原理Closure的实现原理其实就是利用了作用域链的特性。我们都知道作用域链就是访问当前执行环境中的某个变量。如果不存在,就会一直寻找外层,最后找到最外层,也就是Globalscope,这样就形成了一条链。例如:varage=18;functioncat(){age++;console.log(age);//在cat函数中输出age,如果作用域不存在,则寻找外层,找到则输出[19];}cat();//19看到这里大家会说这是函数和变量最简单的形式吗?关闭在哪里?别着急,我们继续往下看:如果再调用一次,结果会一直增加,同时变量age的值也增加了。cat();//20cat();//21cat();//22如果程序有其他函数也需要用到age的值,会受到影响,全局变量容易被别人修改,所以不容易安全,这就是全局变量容易污染的原因,所以必须要解决变量污染的问题,就是把变量封装成函数,做成局部变量。functionperson(){varage=18;functioncat(){age++;console.log(age);}returncat;}person();//19person();//19这里还有一个问题,每次函数person是called,进入这个作用域,变量age会被重新赋值为18,所以cat的值永远是19;所以需要做一些调整:varper=person();//per相当于函数catper();//19是cat()这样每次调用都不会经过age的初始值,这样per();//20per();//21并且age变量在函数内部,不易修改和泄露,相对安全。3、闭包的作用功能一:隐藏变量,避免全局污染功能二:可以读取函数内部的变量,使用闭包不当,优点变成缺点:缺点一:变量不会被垃圾回收机制回收,造成内存消耗缺点2:闭包使用不当可能会造成内存泄漏。我简单解释一下为什么在使用闭包时变量没有被垃圾收集机制收集和销毁。这里我们需要了解一下JS的垃圾回收机制;JS规定在函数作用域内,变量会在程序执行完后销毁,可以节省内存;在使用闭包的时候,根据作用域链的特点,闭包(函数)之外的变量不会被销毁,因为函数会一直被调用,所以一直存在。如果闭包用得太多,内存就会被破坏。四、闭包应用需求:实现变量a自增1、通过全局变量,可以实现,但是会污染其他程序vara=10;functionAdd(){a++;console.log(a);}Add();添加();添加();2。定义一个不污染整个世界但不能自增的局部变量vara=10;functionAdd2(){vara=10;a++;console.log(a);}Add2();Add2();Add2();console.log(a);3.通过闭包可以在不影响所有变量的情况下对函数内部的局部变量自增,完美!!vara=10;functionAdd3(){vara=10;returnfunction(){a++;returna;};};varcc=Add3();console.log(cc());console.log(cc());console.log(cc());console.log(a);
