先花几秒钟来思考一个无厘头的小问题,闭包会导致函数的作用域链发生变化吗?
我们结合下面的例子来分析一下。
var fn = null;
function foo() {
var a = 2;
function innnerFoo() {
console.log(a);
}
fn = innnerFoo; // 将 innnerFoo的引用,赋值给全局变量中的fn
}
function bar() {
fn(); // 此处的保留的innerFoo的引用
}
foo();
bar(); // 2
这个例子中,foo内部的innerFoo访问了foo的变量a。因此当innerFoo执行时会有闭包产生,这是一个比较简单的闭包例子。不一样的地方在于全局变量fn。fn在foo内部获取了innerFoo的引用,并在bar中执行。
那么innerFoo的作用域链会是怎么样的?我们先利用断点调试的方式在浏览器中观察一下,结果如下。
在这里我们需要特别注意的地方是函数调用栈(图右侧Call Stack)与作用域链(Scope)的区别。
因为函数调用栈其实是在代码执行时才确定,而作用域规则在代码编译阶段就已经确定,虽然作用域链是在代码执行时才生成,但是它的规则并不会在执行时发生改变。
所以这里闭包的存在并不会导致作用域链发生变化。