闭包(Closure)概念
全局上下文
一旦<script></script>标签中代码运行起来,就会产生一个执行上下文,这个执行上下文就是全局执行上下文.全局上下文只有一个 全局执行环境是window对象,所有变量和函数都作为window对象的属性和方法创建的 所有的代码都在全局执行上下文中执行
函数执行上下文
每次调用函数都会产生一个执行上下文,函数调用完成后,会把执行上下文释放掉。 按照函数的调用顺序,这些上下文以栈的形式存储(先进后出).栈底是全局上下文。
在JS中,在函数体中可以再次定义另一个函数;并且可以多层函数嵌套使用。
从闭包的定义可以抓住两个关键点: 函数嵌套定义 、引用变量
通过前面的几个相关知识点,可以发现在JS中,函数内部可以通过作用域链机制轻松得到父级函数内的变量乃至全局变量,而反过来则是行不通的,即函数外部是无法读取函数内局部变量的。 那么如果有的场景必须要得到函数内部的局部变量时,需要变通方法那么就产生了闭包。 可以在本质上去理解闭包,闭包就是将函数内部和函数外部连接起来的一座桥梁,可以使局部变量被外部函数访问到,也就是说变相的延长了函数中局部变量的寿命。 上段代码
function f(){
var a = 1;
function f1(){
console.log(a);
}
return f1;
}
var r = f();
r();
这段代码执行后,结果输出为1。也就是说当函数f调用结束后,它的局部变量a并没有被回收掉。可以说这就是闭包的本质,它使得函数调用结束后,被闭包引用的变量没有被回收机制干掉而顺利存活了下来,还可以被外部访问和使用。
根据前面的理解,可以归纳闭包的作用有:
读取函数内部的变量
延长这些变量的生命周期
使用闭包的栗子来一个 - 节流函数 ,可以让一个函数变得"懒",调用一次之后需要隔一段时间才能再次调用,即降低函数的可被调用的频率。话不多说上代码
上面的代码中,f1就是被节流函数变懒了的test。 代码运行中,f函数中t1这个局部变量被f函数内部定义的t函数引用后,当f函数调用执行完毕后,t1这个变量并没有随之被回收,而是一直可以被访问。这就是闭包的体现。