前言
在理解作用域链之前先要知道执行环境。任何函数都有一个执行环境,最外围的是全局执行环境,每一个环境都有自己的活动对象,活动对象里面存在的是当前环境中的变量。
作用域链
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链里存放的是当前环境以及外部环境的活动对象。作用域链的最前端的活动对象始终是当前环境的,下一级就是外部环境,再下一个活动对象来自再下一级的外部环境。当前环境活动对象里如果没有包含函数中使用的变量,那么会沿着作用链去找下一个环境中的活动对象,直到全局环境。这样说可能太晦涩难懂了, 让我们分析一段代码:
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //2
执行fn1其中var a = 2已经成功定义并且a被赋值2,将fn3赋予了fn然后执行fn也就是执行fn3,在fn3中a被定义并赋值4,然后执行了fn2最终结果是2,说明了fn2是从fn1中的活动对象里找到的a。
那我们来看一下图:
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //1
上面的代码最终输出的是1.说明fn2是从全局活动对象里查找到a的声明,所以查找顺序那我们应该看声明fn2的环境,而不是调用fn2的环境。 看图: