ECMAScript规范中非空块语句的VarScopedDeclarations与VarDeclaredNames语义问询
ECMAScript规范中块内var语句的行为解析
先看你提供的代码运行结果:
before block undefined in block before declaration undefined in block after declaration 30 after block 30
核心实现逻辑:函数级作用域与变量提升的规范细节
你已经明确var不属于块级作用域,规范通过以下步骤实现这一特性:
函数初始化的DeclarationInstantiation过程
当函数test被调用时,执行前会触发DeclarationInstantiation流程——这一步会遍历整个函数体的所有代码,收集所有var声明(不管嵌套在多少层块、条件语句等结构里),将这些变量绑定到函数的词法环境中,而非块的独立环境。绑定的初始值为undefined,这就是变量提升的底层逻辑。静态语义的递归收集规则
你疑惑为何没找到Block: { StatementList }的静态语义定义,其实规范的静态语义规则是递归覆盖嵌套场景的:
- 对于
StatementList,其VarDeclaredNames会遍历列表中每个子Statement,收集并合并它们的VarDeclaredNames; Block作为Statement的一种,它的VarDeclaredNames直接等价于内部StatementList的VarDeclaredNames——规范无需单独重复定义,通过递归逻辑自动处理块内的声明收集。
简单来说,不管var写在函数内的哪个位置(包括块内部),都会被DeclarationInstantiation统一收集到函数作用域的绑定中。
- 块内var声明的本质是赋值
代码中块内的var bar = 30,由于bar已经在函数作用域中存在绑定,这里的var声明会被忽略,实际执行的只是赋值操作bar = 30。这也是块内外访问的都是同一个bar变量的原因。
内容的提问来源于stack exchange,提问作者yucj
相关产品推荐
相关产品推荐

