定义
闭包是指那些能够访问⾃由变量的函数
⾃由变量是指在函数中使⽤的,但既不是函数参数也不是函数的局部变量的变量。
所以从技术角度来说,所有的js函数都是闭包。
ECMAScript中,闭包指的是:
- 从理论⻆度:所有的函数。因为它们都在创建的时候就将上层上下⽂的数据保存起来了。哪怕是简
单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问⾃由变量,这个时候使⽤最外
层的作⽤域; - 从实践⻆度:以下函数才算是闭包:
a. 即使创建它的上下⽂已经销毁,它仍然存在(⽐如,内部函数从⽗函数中返回);
b. 在代码中引⽤了⾃由变量
实践
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
执行过程如下:
- 进⼊全局代码,创建全局执⾏上下⽂,全局执⾏上下⽂压⼊执⾏上下⽂栈;
- 全局执⾏上下⽂初始化;
- 执⾏ checkscope 函数,创建 checkscope 函数执⾏上下⽂, checkscope 执⾏上下⽂
被压⼊执⾏上下⽂栈; - checkscope 执⾏上下⽂初始化,创建变量对象、作⽤域链、this等;
- checkscope 函数执⾏完毕, checkscope 执⾏上下⽂从执⾏上下⽂栈中弹出;
- 执⾏ f 函数,创建 f 函数执⾏上下⽂,f 执⾏上下⽂被压⼊执⾏上下⽂栈;
- f 执⾏上下⽂初始化,创建变量对象、作⽤域链、this等;
- f 函数执⾏完毕,f 函数上下⽂从执⾏上下⽂栈中弹出;
当 f 函数执⾏的时候,checkscope 函数上下⽂已经被销毁但是f 执⾏上下⽂维护了⼀个作⽤域链,因为这个作⽤域链,f 函数依然可以读取到 checkscope 函数上下⽂中变量对象的值,说明当 f 函数引⽤了
checkscope 函数上下⽂中变量对象的值的时候,即使 checkscope 函数上下⽂被销毁了,但是JavaScript 依然会让checkscope 函数上下⽂中变量对象活在内存中,f 函数依然可以通过 f 函数的作⽤域链
找到它,正是因为 JavaScript 做到了这⼀点,从⽽实现了闭包这个概念。