JavaScript的作用域链是基于词法作用域,所以在定义函数的时候就已经确定了作用域链是怎样的。
function bar() {
console.log(myName)
}
function foo() {
var myName = " a "
bar()
}
var myName = " b "
foo()
分析上面这段代码的调用栈(执行上下文栈)
全局作用域
- 词法环境:
- 变量环境:function bar() { … }、function foo() { … }、myName = null
- 可执行代码:myName = ‘a’、foo()
foo
- 词法环境:
- 变量环境:myName = null
- 可执行代码:myName = ‘a’、bar()
- bar*
- 词法环境:
- 变量环境:
- 可执行代码:console.log(myName)
bar在去获取myName的时候,会先检查自己的词法环境中是否有myName,没有再去变量环境查找,变量环境也没有,你可能以为会去物理上的下一个执行上下文foo中去寻找,但是开头已经说过,JS的作用域是基于词法环境的,bar在定义的时候,外部是全局作用域,所以bar找不到myName后,实际会去全局作用域去寻找myName,进入全局作用域,也是词法环境->变量环境这个顺序去寻找。那么bar是怎么知道自己的外部作用域是哪个呢,其实每个作用域都有自己的外部引用指向——outer,根据这个每个作用域都会知道自己的外部作用域是哪个了。全局环境肯定是null了,毕竟他是最基础的作用域