在理解做用域链以前先要知道执行环境。任何函数都有一个执行环境,最外围的是全局执行环境,每个环境都有本身的活动对象,活动对象里面存在的是当前环境中的变量。前端
当代码在一个环境中执行时,会建立变量对象的一个做用域链(scope chain)。做用域链里存放的是当前环境以及外部环境的活动对象。做用域链的最前端的活动对象始终是当前环境的,下一级就是外部环境,再下一个活动对象来自再下一级的外部环境。当前环境活动对象里若是没有包含函数中使用的变量,那么会沿着做用链去找下一个环境中的活动对象,直到全局环境。这样说可能太晦涩难懂了, 让咱们分析一段代码:bash
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的环境。 看图: ui