1.定义和理解
首先在高级程序设计中对于闭包概念是这样定义的:“闭包是指有权限访问另一个函数作用域中的变量的函数。“
意思就是函数a能访问到函数b作用域下的变量那么函数a就是闭包,在网络上有些文章指出闭包有两个条件:
1.函数嵌套,内部函数要用到外部函数的局部变量 2、内部函数必须返回
同时也有些人认为不要返回内部函数也可以称之为闭包,我们从高级程序设计中对于闭包概念定义来分析就是即使没有返回内部函数也是闭包。
我们可以参考一下阮一峰老师对闭包的理解:(由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁)
2.环境变量
要理解闭包,首先必须理解Javascript特殊的变量作用域。在js中变量的作用域无非就是两种:全局变量和局部变量。局部变量写在函数体内,局部变量省略了var 也就默认成为了全局变量!
var a=15 // 变量a定义在函数外面也就是全局变量在该js中任何地方都可以访问
function out() {
console.log(a) // 函数out里面是可以直接访问全局变量
}
out()
在这里a就是全局变量,如果在nodejs中还有顶层对象,在浏览器环境指的是window
对象,在Node指是的global
对象,ES5之前中,顶层对象的属性与全局变量是等价的。
ES6规定,var
命令和function
命令声明的全局变量,依旧是顶层对象的属性;let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性这里就不再陈述。
var a=15 // 变量a定义在函数外面也就是全局变量在该js中任何地方都可以访问
function out() {
var b=20 // 变量b定义在函数out里面,变量是局部变量
console.log(a) // 函数out里面是可以直接访问全局变量
}
out()
console.log(a)//在这里打印变量a是可以访问到的
console.log(b)//在这里打印变量b是无妨访问的
在这个例子中我们可以看到函数out可以访问全局变量a,但是在函数外部是访问不到out函数里面的局部变量b
var a=15 // 变量a定义在函数外面也就是全局变量在该js中任何地方都可以访问
function out() {
var b=20 // 变量b定义在函数out里面,变量是局部变量
c=30// 变量c没有使用var,所有c也是全局变量
console.log(a) // 函数out里面是可以直接访问全局变量
}
out()
console.log(a)//在这里打印变量a是可以访问到的
console.log(c)//在这里打印变量是才可以访问到的
console.log(b)//在这里打印变量b是无妨访问的
这个例子就是局部变量省略了var 也就默认成为了全局变量!所有大家在定义变量的时候要注意
总结:Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,在函数外部自然无法读取函数内的局部变量。
3.外部读局部变量(闭包)
在我进行编程过程中出于种种原因,我们有时候需要得到函数内的局部变量。但是,由于变量的作用域,正常情况下,这是办不到的,只有通过变通方法才能实现。
function a() {
var x=10;
function b() {
console.log(x)
}
b()
}
a()
在这个例子中函数b要是想访问函数a里面的变量x,如何直接把函数b放到函数a外面,函数b里面是输出不了变量x,所有我们将函数b放到了函数a里面,然后运行函数b,这个时候函数b就可以正常访问到函数a的变量x,因为函数b位于函数a里面所以是可以访问到函数a作用域下的变量。
function f1(){
var n=999;
function f2(){
console.log(n)
}
return f2;
}
var result=f1();
result()
这里给大家展示一个阮一峰老师的一个例子:既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
上面代码中的f2函数,就是闭包,我的理解就是:闭包,指的是在函数里的函数。(其实闭包就是被嵌套的那个函数)
4.闭包的作用
闭包可以读取函数内部的变量,可以让变量的值始终保持在内存中。
通过闭包我们可以在函数外部读取函数内部的变量,简单来说闭包就是将函数的外部和内部进行了连接