介绍
本文是 JavaScript 高级深入浅出系列的第三篇,详细介绍了作用域链的查找规则
正文
在第二篇中,我们在解析执行函数的过程中,提到了console.log将找到父级作用域中的 console 类,最终找到 log 方法,接下来我们将详细了解这一过程。
var name = 'alex'
foo()
function foo() {
console.log(name) // alex
}
在foo函数中并未定义 name,那么就说明该函数所属的AO中并没有 name。但是由于全局对象 GO 中有 name,所以最终打印出 alex。实际上,要找一个变量是根据作用域链查找的。
在函数所属的 FEC 中,除了有 AO,其实还有 scope chain,也就是作用域链
scope chain由两部分组成:
- 当前作用域的 AO
- 父级作用域 parent scope
在上文的代码片段中,foo的 parent scope 就是全局作用域,因此在寻找name变量时,首先会在自己的 AO 中寻找,找不到就会在父级作用域中的 VO 也就是 GO 中寻找,假设父级作用域还没有,就会去父级作用域的父级作用域中找,最终找到 name 并打印
举例说明
var name = 'alex'
foo()
function foo() {
var n1 = 123
function bar() {
var n2 = 456
console.log(name)
}
bar()
}
在执行阶段:
- 当执行
bar函数中的console.log(name)时,开始在所属 AO 中找,并没有 name - 接下来会根据所属 FEC 中的 parent scope 去找
foo函数中是否有 name - 在 foo 的 AO 中还没有,将根据 foo 所属的 FEC 中 parent scope 去找 name
- 最终在全局对象 GO 中找到 name,并打印
bar函数执行完毕,所属 FEC 弹出 ECStackfoo函数执行完毕,所属 FEC 弹出 ECStack
总结
本文中,你学到了一个知识:
作用域链的查找规则
在函数的 FEC 内部,会存在一个 scope chain,由本作用域的 AO + 父级作用域组成。
在查找某个变量时,在所属 AO 中找不到就会沿着 scope chain 一层一层往上查找,直到找到或 GO 中找不到报错为止。