块级作用域无execution context时如何访问外层作用域变量?
块级作用域变量访问机制说明
先看你给出的示例代码:
function first(){ let i=10; function second(){ let j=20; console.log(i); if(j==20){ console.log(i); } } second(); }
你的疑问核心是混淆了执行上下文和词法作用域的作用边界,核心逻辑可以拆解为3点:
- 只有全局代码执行、函数调用、eval执行三类场景会创建新的执行上下文,if/for这类块级代码确实不会生成独立的执行上下文,也没有独立的执行上下文级别的作用域链。
- 词法作用域的规则是在代码预编译阶段就静态确定的,和运行时的调用逻辑无关。你示例里的if块属于
second函数词法作用域内部的子块,本身就处于second的作用域覆盖范围内。 - 块级代码运行时,用的就是所属外层函数的执行上下文的作用域链。
具体到你的代码运行过程:
- 调用
first()时创建first的执行上下文,作用域链为[first变量对象, 全局变量对象],变量i存储在first的变量对象中。 - 执行到
second()调用时创建second的执行上下文,作用域链为[second变量对象, first变量对象, 全局变量对象],变量j存储在second的变量对象中。 - 第一个
console.log(i)执行时,沿second的作用域链查找,在first的变量对象中找到i=10完成输出。 - 进入if块时不会创建新的执行上下文,当前执行上下文仍然是
second的,所以第二个console.log(i)还是沿second的作用域链查找i,和第一个的查找逻辑完全一致,自然能拿到对应的值。
补充说明:如果块内用let/const声明了同名变量,这些变量会存储在当前执行上下文变量对象的块级变量存储区,查找时会优先匹配块级变量,再匹配函数级变量,最后沿作用域链向上查找,整个过程都不需要新增执行上下文。
内容的提问来源于stack exchange,提问作者Manishpant
相关产品推荐
相关产品推荐

