# 闭包
闭包也算是js绕不过去的一个议题了。
# 概念
闭包是指那些能够访问自由变量的函数
那么什么是自由变量呢?
自由变量是指在函数中使用的, 但是既不是函数参数也不是函数的局部变量的变量。
所以
闭包 = 函数 + 函数能够访问的自由变量
来个例子
let a = 1;
function foo() {
console.log(a);
}
函数foo
+ 变量a组成了一个闭包。从技术的角度讲,函数就是一个闭包。
ECMAScript中,闭包指的是:
- 从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
- 从实践角度:以下函数才算是闭包:
- 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)
- 在代码中引用了自由变量
举几个面试题的例子吧
var scope = 'global scope';
function checkscope() {
var scope = 'local scope';
function f() {
return scope;
}
return f;
}
var foo = checkscope();
console.log(foo()); // local scope
函数foo的作用域链上维护了checkscope函数的活动对象, 虽然checkscope已经执行完出栈了, 但是他的局部变量scope还保存在foo的作用域链上,(造成了内存泄漏)。这段demo满足从实践角度来解释闭包。
必刷题
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
答案都是3,此时也是闭包,只不过外部自由变量i变成了3. 所以都打印3.
稍作修改变成打印 0 1 2.
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = (function (i) {
return function () {
console.log(i);
};
})(i);
}
data[0]();
data[1]();
data[2]();
更加详细的还是看下面的链接吧。从作用域链和活动对象来分析, 更加的合理。
← Javascript继承 块级 作用域 →