一、先理解什么是词法作用域。
词法作用域:
词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的
- 包含着整个全局作用域,其中只有一个标识符:foo。
- 包含着 foo 所创建的作用域,其中有三个标识符:a、bar 和 b。
- 包含着 bar 所创建的作用域,其中只有一个标识符:c。
二、闭包
闭包定义:
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
e.g.
function foo() { var a = 2; function bar() { console.log( a ); } return bar; } var baz = foo(); baz(); // 2 —— 朋友,这就是闭包的效果。
在 foo() 执行后,通常会期待 foo() 的整个内部作用域都被销毁,因为我们知道引擎有垃圾回收器用来释放不再使用的内存空间。由于看上去 foo() 的内容不会再被使用,所以很自然地会考虑对其进行回收。
而闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在,因此没有被回收。谁在使用这个内部作用域?原来是 bar() 本身在使用。
拜 bar() 所声明的位置所赐,它拥有涵盖 foo() 内部作用域的闭包,使得该作用域能够一直存活,以供 bar() 在之后任何时间进行引用。
bar() 依然持有对该作用域的引用,而这个引用就叫作闭包。