闭包?
关于闭包我想很多学习js的同学都有所听说,网上关于闭包的概念解释,也是五花八门,经过我对js高级内容的深度学习,终于理解了所谓闭包。
首先我们先看一个w3schllo官方文档中对于闭包的解释:
闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。
概括起来就是说:闭包可以在一个作用域中可以访问另一个作用域的变量。
可能这句解释也并不太合理,我们通过一些代码,让大家感受一下什么是闭包!
我们先来看一下这几行代码:
function fn(){
var a = 6;
return a;
}
fn();
我们首先声明了一个函数,函数中定义了一个变量a并赋值,然后把a作为函数中的返回值返回。以上代码片段中,变量a 是定义在函数作用域中的,当函数执行完毕后,函数作用域会被销毁,那么在外部无法访问到变量a。
我们打开浏览器按f12看一下执行原理。
点击Sources在源代码中的var = a;该行打一个断点;
我们可以看到程序执行到这一行时产生了一个新的作用域,因为这一行还没有执行,所以此时a为undefined,因为函数时window调用,故this指向window.下面按f11继续执行,当函数执行完毕后,我们发现
Scope中的局部作用域被销毁了。当函数执行完毕后,作用域被销毁,那么我们有没有一种方式可以将变量a,储存起来呢?请同学们看下面代码:
function fn(){
var a = 6;
return function(){
return a;
}
}
var f = fn();
console.log(f());
这样写可能很多同学看起来会觉得比较奇怪,在高阶函数中,函数不仅可以作为返回值,还可以作为参数,因为函数也是对象。
我们都知道局部作用域外部无法访问内部的局部变量,但是函数中还可以声明函数,函数内部的函数可以访问函数外部的成员变量,因此我们可以将函数作为fn()的返回值,并且将a返回给返回值函数,然后声明一个变量f接收fn()返回的函数。
再来执行一下,打开控制台,继续debug.我们可以看到当执行到fn()返回值的时候:
产生了一个Closure,这就是闭包,在闭包里可以看到有a的属性,我们可以理解为,闭包其实就是将函数中的变量a进行了复制,然后我们就可以通过访问返回的函数的返回值进行访问函数中的局部变量。这是控制台也可以看到6被输出了。
那么什么时候用到闭包呢,我想大多数同学已经知道了。就是当一个函数或者一块作用域中需要访问另一个作用域中的局部变量,我们可以使用闭包的方式解决。
js虽然说有的地方很复杂,但我们只要搞懂了原理,学会自己去发现问题,解决问题。回头一想,其实也就那么回事!