想要了解闭包,需要先了解作用域
全局作用域
定义变量全局都可以使用,且会一直占用内存,不会被销毁
函数作用域
函数内部自己定义的变量,一般只能自己访问,且只有在函数被调用时,才会被分配内存空间,一但执行完毕,当即销毁
块级作用域
类似与函数作用域,如for循环就是一个块级作用域,但是var是没有块级作用域的,它只有全局作用域。
{
let a = 1
var b = 1
}
console.log(b) //=>1
console.log(a) //=>a is not defined
//使用var定义
for (var a = 1; a <= 4; a++) {
}
console.log(a)//=>5
//使用let定义
for (let a = 1; a <= 4; a++) {
}
console.log(a)//a is not defined
闭包的产生
因为有作用域的原因,函数可以访问其外部作用域的变量,而外部无法直接访问函数内部的变量,所以需要使用一些技术,使得外部可以访问,这就是闭包。
一个简单的闭包的实现
原
function fn1() {
let a = 1;
}
console.log(a)//=> a is not defined
使用闭包
function fn1() {
let a = 1;
return function fn2() {
return a
}
}
var result = fn1()
console.log(result())//=>1
闭包实现步骤
1、首先要有一个需求,假设有一个函数A,A函数内部有个变量,我们需要在A的外部使用这个变量。
2、那么我们可以在A函数的内部定义一个B函数,让B函数使用A的变量,最后将其返回,使得外部可以调用。
思考一个问题
如果想要获得内部数据不可以直接return吗?
如:
function fn1() {
let a = 1;
return a
}
var result = fn1
console.log(result())//=>1
可以获得数据,但是会产生一个问题:假设我们需要实行一个计数器。
function fn1() {
let a = 1;
a++
return a
}
var result = fn1
console.log(result())//=>2
console.log(result())//=>2
执行了两次result函数,但是a的值没有+1,一直都是2。
那么是什么问题呢?
闭包实现的原理
1、产生上面那个问题的原因,是因为,当函数执行结束后,就会被销毁,而第二次产生的是一个新函数,因此不会+1。
2、当我们使用闭包时,在里面定义的一个函数,且使用了外部函数的数据,那么因为它还在被使用,所以不会被立即销毁,数据得以保存。
如:
function fn1() {
let a = 1;
return function fn2() {
a++
return a
}
}
var result = fn1()
console.log(result())//=>2
console.log(result())//=>3
闭包的作用
1、数据留存
就像上面例子一样,实现简单的计数
2、数据交互
外部可以访问内部的数据
3、封装私有变量