Javascript 当AST已经知道值时,为什么此代码返回undefined

Javascript 当AST已经知道值时,为什么此代码返回undefined,javascript,parsing,undefined,abstract-syntax-tree,lexical-analysis,Javascript,Parsing,Undefined,Abstract Syntax Tree,Lexical Analysis,var name='ali' 函数sayHi(){ console.log(名称); 控制台日志(年龄); 变量名称='Lydia'; 年龄=21岁; } sayHi()该代码段中有两个同名的变量(name)。如果仔细查看生成的AST,您将看到这两个声明 AST没有显示这两个声明的作用域,这是一个重要方面。变量的范围是程序中变量名称可见的区域;也就是说,与变量关联。两个变量同名是完全合法的;如果它们的作用域重叠,则内部作用域将覆盖外部作用域 所有这些对于大多数编程语言来说都很常见,但是ECMAS

var name='ali'
函数sayHi(){
console.log(名称);
控制台日志(年龄);
变量名称='Lydia';
年龄=21岁;
}

sayHi()
该代码段中有两个同名的变量(
name
)。如果仔细查看生成的AST,您将看到这两个声明

AST没有显示这两个声明的作用域,这是一个重要方面。变量的范围是程序中变量名称可见的区域;也就是说,与变量关联。两个变量同名是完全合法的;如果它们的作用域重叠,则内部作用域将覆盖外部作用域

所有这些对于大多数编程语言来说都很常见,但是ECMAScript的作用域规则要比一般的规则复杂得多(这就是为什么AST工具可以显示作用域的部分原因)。ECMAScript具有两组不同的作用域规则,一组用于使用
var
声明的变量,另一组用于使用
let
const
声明的变量

虽然这个简单的示例没有显示所有的差异,但它确实显示了一个重要的差异:虽然内部
var
-声明的
名称可以在初始化之前使用,导致值
未定义
,但是
let
-声明的
年龄
在初始化之前不能使用,导致抛出错误。(
声明的变量在初始化之前处于所谓的“暂时死区”中。)

本例中未显示的差异是函数
sayHi
中声明的变量范围的边界。
var
声明变量的作用域是在其中声明的最内层函数体(包括在同一作用域中声明的任何函数,除非它们具有相同名称的重写声明)。另一方面,
let
声明的变量的范围仅限于最里面的封闭块。但在本例中,内部
var name
let age
的最内层封闭块是函数
sayHi
的主体

在ECMAScript中,变量的作用域始终是整个块。这与C等语言形成对比,在C语言中,变量的范围仅从变量的声明扩展到封闭块的末尾。在这种情况下,这会有所不同:在C作用域规则下,
console.log(name)
中的
name
将引用外部声明,因为内部声明在代码中的位置较低,因此其作用域尚未启动。和
console中的
age
。log(age)
将是非法的,因为没有声明
age
的封闭范围。但在ECMAScript中,声明被“挂起”以包含整个块,从而产生了暂时死区的可能性


虽然这可能已经包含了太多的信息,但我应该注意到,我并没有真正涵盖ECMAScript或C中作用域的所有奇怪之处,其他语言也有其他微妙不同的作用域规则。

添加
“使用strict;”
最重要的是,JavaScript应该抛出一个引用错误:在初始化之前无法访问'age'。我知道这一点,我想知道为什么当抽象语法树已经知道该值时,该值会抛出eror,因为如果试图使用
let
来定义变量,ECMAScript就会这样定义(或
const
)。我无法发送图像。但你能将此代码粘贴到网站上并查看吗?我不需要。我不在乎一些不知道ECMAScript规则的网站会说什么。一旦ECMAScript规则生效,AST“知道”就无关紧要了有些东西。规则说如果你试图访问它,就会抛出一个错误。所以当你试图访问它时,就会抛出一个错误。谢谢你的回答。这对我很有帮助。