闭包的定义有很多,但是被定义的对象确是一样的,只不过看待问题的角度不一样罢了。都是研究是函数跟它的作用域合在一起的一种类似于生态体系的样子,好像母体和胎儿的意思,毕竟函数的声明本身就是也限定了它的作用范围,引用的变量等等都与作用域有关。
词法作用域
函数的各个变量需要有声明的,否则就是undefined,要找声明,先从内部找,再从函数当前所在的作用域(词法作用域)找,依次往上。
函数连同它作用域链上找的这个变量,共同构成闭包。
作用:
- 封装数据
- 暂存数据
例子:
function car(){
var speed = 0
function fn(){
speed++
console.log(speed)
}
return fn
}
var speedUp = car() //逻辑就是先运行car(),就要运行fn(),就要找变量speed
speedUp() //1
speedUp() //2
如果没有里面的fn()返回出来赋值给speedUp,speed运行了就销毁了。
全局作用域的speedUp是一直存在的,除非关闭页面,才会销毁变量,局部的是运行完以后就销毁,所以fn也是一直存在的,fn的作用域也要存在,变量speed就保存了。上面的可以这样:
var speed = 0
function fn(){
speed++
console.log(speed)
}
fn() //1 这就是闭包的两个要素,函数和变量。
fn() //2这里没有return fn所以没形成闭包,执行了就被销毁了。
fn() //3
案例
var fnArr =[]
for (var i =0;i<10;i++){
fnArr[i] =function(){
return i
}
}
console.log(fnArr[3]()) //10不是3,为什么?要fnArr[3](),就要执行里面的function,就要return i,
//在哪里,在全局的for循环里,所以,这时候for循环早执行完了。
如图:
global全局作用域哦。
改造:
var fnArr=[]
for(var i=0;i<10;i++){
fnArr[i]=(function(j){
return function(){
return j
}
})(i)
}
console.log(fnArr[3]()) //3
立刻执行的函数,这时候的i=3造成了
(function(j){
return function(){
return j
}
})(i)的i等于3,这时候相当于:
var fn =function(j){
return function(){
return j
}
执行fn(3),相当于找j的值,相当于在函数内加了var j=arguments[0]
//i=3赋值给一个临时变量,返回这个临时变量就是这个意思了。
var fnArr=[]
for(var i=0;i<10;i++){
(function(i){
fnArr[i] = function(){
return i
}
})(i)
}
console.log(fnArr[3]())//3
这里也是将i=3的值封装进了return i的包里了,这就是作用域与函数的奇妙结合,避免了全局下的i值为10。
var fnArr=[]
for(let i=0;i<10;i++){
fnArr[i]=function(){
return i
}
}
console.log(fnArr[3]()) //3这里是let的用法,作为拓展的,没有闭包的相关。
网友评论