Javascript ES6中有关“let”和块范围的吊装

Javascript ES6中有关“let”和块范围的吊装,javascript,ecmascript-6,Javascript,Ecmascript 6,当我运行使用ES6编写的以下代码时,让: 函数doSmth(){ 年龄=27岁; } 让年龄; doSmth(); 控制台日志(年龄)“Let has block scope”并不意味着必须在同一块中定义变量-它意味着定义变量的级别可以是块 相反,定义var变量的级别不能是块,除非该块也是功能块。如果var变量在非功能块内初始化,它将被提升到最近的外部块(也是功能块) 无论变量是用var、let还是const声明的,它都可以在声明它的同一块内的任何其他地方引用,包括在子块内。(对于let和co

当我运行使用ES6编写的以下代码时,让:

函数doSmth(){
年龄=27岁;
}
让年龄;
doSmth();
控制台日志(年龄)“Let has block scope”并不意味着必须在同一块中定义变量-它意味着定义变量的级别可以是块

相反,定义
var
变量的级别不能是块,除非该块也是功能块。如果
var
变量在非功能块内初始化,它将被提升到最近的外部块(也是功能块)

无论变量是用
var
let
还是
const
声明的,它都可以在声明它的同一块内的任何其他地方引用,包括在子块内。(对于
let
const
,声明变量的行,例如
const foo=
,也必须运行对
foo
的引用,才能在不抛出的情况下工作。)

另一种方法是:如果某个变量在某个地方被引用,解释器将查找它是否在当前块中初始化。如果是这样,则使用的是绑定。否则,它会在下一个外部块中查看变量是否在那里初始化——如果是,则使用的是绑定。等等如果它一直到达顶层,并且没有找到绑定,并且它不是全局对象的属性,那么该引用将抛出一个
ReferenceError

在您的代码中,
age
变量恰好是全局变量,因为它是在顶层定义的,但这并不重要-如果
age
只是一个外部块,但不在顶层,则代码的工作原理相同,例如:

函数foo(){
函数doSmth(){
年龄=27岁;
}
让年龄;
doSmth();
控制台日志(年龄);
}
foo()“Let has block scope”并不意味着必须在同一块中定义变量-它意味着定义变量的级别可以是块

相反,定义
var
变量的级别不能是块,除非该块也是功能块。如果
var
变量在非功能块内初始化,它将被提升到最近的外部块(也是功能块)

无论变量是用
var
let
还是
const
声明的,它都可以在声明它的同一块内的任何其他地方引用,包括在子块内。(对于
let
const
,声明变量的行,例如
const foo=
,也必须运行对
foo
的引用,才能在不抛出的情况下工作。)

另一种方法是:如果某个变量在某个地方被引用,解释器将查找它是否在当前块中初始化。如果是这样,则使用的是绑定。否则,它会在下一个外部块中查看变量是否在那里初始化——如果是,则使用的是绑定。等等如果它一直到达顶层,并且没有找到绑定,并且它不是全局对象的属性,那么该引用将抛出一个
ReferenceError

在您的代码中,
age
变量恰好是全局变量,因为它是在顶层定义的,但这并不重要-如果
age
只是一个外部块,但不在顶层,则代码的工作原理相同,例如:

函数foo(){
函数doSmth(){
年龄=27岁;
}
让年龄;
doSmth();
控制台日志(年龄);
}

foo()在代码中,doSmth和age都在全局范围内。浏览器的窗口和节点的模块对象。所以它们基本上在同一个范围内

在您的代码中,doSmth和age都在全局范围内。浏览器的窗口和节点的模块对象。所以它们基本上在同一个范围内

现在我有点搞不清楚这是怎么回事。具体地说,我读到的是
let
有一个块范围

是,
let
具有块范围。但是,诸如
dosmth()
函数内部的块可以访问父作用域中在函数执行时定义或提升的所有变量

所以,
let age在父作用域中,并且在执行
doSmth()
时已定义。因此,负责查找名为
age
的变量的解释器可以在父范围中找到它

那么,在函数
doSmth
之外声明的
let age
,是如何在函数doSmth内部声明相同的变量的呢

以下是译员在这方面的工作方式。代码按以下步骤执行:

  • 解析您提供的代码
  • 遇到
    函数doSmth()
    定义。函数被提升到包含函数作用域的顶部,以便将定义立即添加到此作用域对象<解析过程中也会遇到code>let age
  • ,并将其添加到已解析的作用域中,但其标记方式使代码无法访问
  • 开始执行代码。将根据解析的代码创建一个新的范围对象
  • let年龄。这将
    age
    变量标记为现在可供代码使用,该变量以前在解析时放入此范围
  • 调用
    doSmth()
    。这将在调用堆栈上推送一个返回地址,当它设置为执行
    doSmth()
    ,它将创建一个新的函数作用域
  • 然后在该函数内执行
    age=27
    。解释器在本地范围中查找名为
    age
    的符号。它找不到。因此,它沿着作用域链向上并查看父作用域。它找到一个匹配的s
    doSmth();
    console.log(age);