定义(出自《你不知道的JavaScript(上卷)》):
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
词法作用域即静态作用域
用一些代码来解释一下上面的定义
function foo() {
var a = 2;
function bar() {
console.log( a ); // 2
}
bar();
}
foo();
这是闭包吗?
从技术上讲也许是,但是根据前面的定义,确切的说不是闭包。
虽然这段代码中bar()确实访问了自己所在的词法作用域(即foo()的函数作用域),但是并没有记住自己所在的作用域
下面这段代码,则是清晰的展示了闭包
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 —— 朋友,这就是闭包的效果。
这段代码中bar()不仅通过var baz=foo()记住了自己所在的词法作用域,而且可以通过调用baz()来访问自己所在的词法作用域。即使函数是在当前词法作用域之外执行。
参见:《你不知道的JavaScript(上卷)》
2020年11月02日更
最新看了《javaScript的设计模式和开发实战》,觉得这里对闭包的讲解更容易理解,所以在这里做个笔记。
这里是从变量的生存周期切入,来讲解闭包。
对于全局变量来说,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。而对于在函数内用var关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了它们的价值,它们都会随着函数调用的结束而被销毁:
var func = function () {
var a = 1; // 退出函数后局部变量a将被销毁
a++;
console.log(a);
};
func(); // 输出:2
func(); // 输出:2
func(); // 输出:2
func(); // 输出:2
现在来看看下面这段代码:
var func = function () {
var a = 1;
return function () {
a++;
console.log(a);
}
};
var f = func();
f(); // 输出:2
f(); // 输出:3
f(); // 输出:4
f(); // 输出:5
跟我们之前的推论相反,当退出函数后,局部变量a并没有消失,而是似乎一直在某个地方存活着。这是因为当执行var f= func();时,f返回了一个匿名函数的引用,它可以访问到func()被调用时产生的环境,而局部变量a一直处在这个环境里。既然局部变量所在的环境还能被外界访问,这个局部变量就有了不被销毁的理由。在这里产生了一个闭包结构,局部变量的生命看起来被延续了。
本文详细解析了JavaScript中闭包的概念,通过实例说明了闭包如何使函数记住并访问其词法作用域,即使在外部执行。探讨了局部变量的生命延续,展示了闭包在实际编程中的应用。

被折叠的 条评论
为什么被折叠?



