1.什么是闭包
闭包是一个函数以及其捆绑的周边环境状态的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。
简单来说,闭包就是把全局可使用的量缩小到局部可使用的量(相当于封闭了)
2.闭包的使用
这里举一个简单的例子,构造一个累加(减)函数,每调用一次执行一次加(减)
let x = 10;//这是一个全局变量,此处的所有函数都可以访问到,并对其操作
function f1(){
return console.log(--x) ;
}
function f2(){
let y = 0;//这是一个局部变量,只有f2内部可以访问到,并对其操作
return console.log(++y);
}
f1()
f1()
f1()
console.log("-------")//分界线
f2()
f2()
f2()
运行结果如下:
从结果可以看到,f1通过全局变量的驻存(不被重新赋值变量而覆盖),可以达到累减的效果,而f2因为局部变量,每次调用都被重新赋值只能得到一次结果。
虽然f1达到了需求,但是f1用的全局变量可以被其他地方任意修改,同时也要耗费更多的内存(处于顶端的空间,所有的函数都能访问使用),所以使用闭包的方式可以避免这些情况。
闭包能达到的效果:
1.将全局变量缩放到函数内部(一个代码块中),将其与外部隔绝开,仅能在此内部访问
2.减少内存消耗
function f3() {
let i = 0;//局部变量,f3的内部私有量(相当于private量),只有f3内部可以访问到,并对其操作
function add() {
i++;//向上索引到私有量i
console.log(i);
}
return add;
}
let fn = f3();//使用外部对象接受返回的函数
console.log("-------")//分界线
f1()
f1()
f1()
console.log("-------")//分界线
f2()
f2()
f2()
console.log("-------")//分界线
fn()
fn()
fn()
运行结果如下
可以看到闭包成功实现了累加,同时没有使用全局变量。
细节分析
仔细对比f1,f3我们可以发现f3相当于在f1上套了一层函数
也就是说f1的作用和f3内的add()函数是一样的,即f3的作用是框住变量,add的作用才是执行的累加操作。
3.闭包的判断
通过上面的例子,我们能够理解到闭包的结构有这么几个:
1.函数的嵌套 (外部函数用来驻存变量)
2. 局部变量的创建 (驻存的私有变量)
3.返回了函数 (真正执行操作的函数)
4.有外部对象接受返回的函数 (拿到返回的函数操作)
总结
闭包,拥有一个区域量且可以对它执行操作的函数结构
完整代码展示和扩展内容
//闭包:可以将全局公共的值存为局部私有的值
let x = 10;//这是一个全局变量,此处的所有函数都可以访问到,并对其操作
function f1(){
return console.log(--x) ;
}
function f2(){
let y = 0;//这是一个局部变量,只有f2内部可以访问到,并对其操作
return console.log(++y);
}
function f3() {
let i = 0;//局部变量,f3的内部私有量(相当于private量),只有f3内部可以访问到,并对其操作
function add() {
i++;//向上索引到私有量i
console.log(i);
}
return add;
}
let fn = f3();//使用外部对象接受返回的函数
let fm = (function(){
let j=10;
return function(){
j--;
console.log(j)
}
})()
console.log("-------")//分界线
f1()
f1()
f1()
console.log("-------")//分界线
f2()
f2()
f2()
console.log("-------")//分界线
fn()
fn()
fn()
console.log("-------")//分界线
fm()
fm()
fm()
想必你已经对闭包有一定的了解了,以下简化了一个函数结构,你能判断它是否是闭包并够理解它的含义吗
let fm = (function(){
let j=10;
return function(){
j--;
console.log(j)
}
})()