准确来说,闭包是基于正常的垃圾回收处理机制下的。也就是说,一般情况一个函数(函数作用域)执行完毕,里面声明的变量会全部释放,被垃圾回收器回收。但闭包利用一个技巧,让作用域里面的变量,在函数执行完之后依旧保存没有被垃圾回收处理掉。
闭包
MDN定义
javascriptkit
词法作用域
<>强闭包的三大特点为:强>
1,函数嵌套函数
2,内部函数可以访问外部函数的变量
3,参数和变量不会被回收。
函数在执行的过程中,先从自己内部找变量如果找不到,再从创建当前函数所在的作用域(词法作用域)去找,以此往上注意找的是变量的当前的状态
作用域链的博客
函数连同它作用域链上的要找的这个变量,共同构成闭包
一般情况下使用闭包主要是为了
-
<李>封装数据李>
<李>暂存数据
李>
函数的车(){ var速度=0 函数fn () { 速度+ + console.log(速度) } 返回fn } var加速车=() 加速()//1 加速()//2
当函数内部没有执行以下的代码时
函数fn () { 速度+ + console.log(速度) } 返回fn
在代码执行完成后,函数内部的局部变量速度就会被销毁,由于全局标量加速一直存在(除非关闭当前页面,否则全局变量一直存在),那么函数内部的作用域就没有办法被销毁,里面有东西一直被使用,这点与浏览器的垃圾回收机制相仿,当我们执行加速(),他会在函数的词法作用域下去寻找,函数里面又返回了一个fn,因而形成闭包,简单的理解为
var速度=0 函数fn () { 速度+ + console.log(速度) }
这一段代码形成一个闭包,如果不返回fn,那函数内部的局部变量就会被销毁。
我们可以看看上述代码利用立即执行语句和立即执行函数可以怎么演变:
函数的车(){ var速度=0 函数fn () { 速度+ + console.log(速度) } 返回fn } var加速车=()//1 函数的车(){ var速度=0 返回函数(){ 速度+ + console.log(速度) } } var加速车=()//2 函数汽车(速度){ 返回函数(){ 速度+ + console.log(速度) } } var加速=车(3)//3 函数的车(){ var速度=参数[0] 返回函数(){ 速度+ + console.log(速度) } } var加速车=()//4 函数的车(){ var速度=0 返回函数(){ 速度+ + console.log(速度) } }//5车可以不写,则为匿名函数 var加速=(功能汽车(速度){ 返回函数(){ 速度+ + console.log(速度) } } )(3)
如下代码输出多少?如果想输出3,那如何改造代码?
var fnArr=[]; (var=0;我& lt;10;我+ +){ fnArr[我]=function () { 返回我 }; } 控制台。日志(fnArr [3] ())//10
同等演变
假设只有两层循环:
var fnArr=[] (var=0;我& lt;2;我+ +){ fnArr[我]=(函数(j) { 返回函数(){ 返回j } })(我) } fnArr [3] ()//1 var fnArr=[] fnArr[0]=(函数(j) { 返回函数(){ 返回j } })(0) } fnArr[1]=(函数(j) { 返回函数(){ 返回j } })(1) } fnArr [3] ()//2 var=(函数(j) { 返回函数(){ 返回j } })(0) } var b=(函数(j) { 返回函数(){ 返回j } })(1) } b ()//3 var=(函数(j) { 返回函数(){ 返回j } })(0) } 函数fn2 (j) { 返回函数(){ 返回j } } var b=fn2 (1)//4 var=(函数(j) { 返回函数(){ 返回j } })(0) } 函数fn2 (j) { 返回函数(){ 返回j } 返回f } var b=fn2 (1)//5 var=(函数(j) { 返回函数(){ 返回j } })(0) } 函数fn2 (j) { var j[0]=参数 函数f () { 返回j } 返回f } var b=fn2 (1)js中的闭包实例展示