词法作用域:
- 词法作用域就是指作用域是由代码中函数声明的位置来决定的
- 词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。
- 内部函数总是可以访问它们的外部函数 中的变量
有下面代码
<script>
function foo() {
var myName = "1"
bar()
}
function bar() {
console.log(myName)
}
var myName = "2"
foo()
</script>
- 全局作用域
编译阶段
执行上下文的变量环境
function foo () {...}
function bar () {...}
myName = undefined
可执行代码
myName = 2
foo()
执行阶段, 执行maName = 2 和 foo() - foo函数作用域
编译阶段
执行上下的变量环境
myName = undefifned
可执行代码
myName = 1
bar()
执行阶段, 执行myName = 1 和 bar() - bar函数作用域
编译阶段
执行上下文的变量环境和词法环境均没有对象引用
可执行代码
console.log(myName)
调用栈图示如下
outer:每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文
1.当JS执行全局代码的时候会先编译全局代码并创建执行上下文
2.全局代码编译完成,执行赋值操作 myName = 2
3.执行foo(), foo函数符合‘一段代码’, 需要先被编译,编译完成后执行
4.foo函数编译完成,执行赋值操作 muName = 1
5.执行bar(), bar函数符合‘一段代码’, 需要先被编译,编译完成后执行
6.执行到console.log(myName)的时候, 在bar的词法环境和变量环境均未查找到myName, 便去outer指向的作用域去查找
7.此时outer指向于 全局作用域(bar函数在全局作用域的执行上下文的变量环境中被定义)
8.在全局可执行上下文中的变量环境中找到maName并打印2
如果把代码改一下,下面的代码就会打印1,原理同上
<script>
function foo() {
var myName = "1"
bar()
function bar() {
console.log(myName)
}
}
var myName = "2"
foo()
</script>