有谁能解释一下为什么我们在这段代码中重新声明了let x=5,而这段代码却显示错误?它应该显示由于词法作用域的错误。
function demoFunction() {
let x = 10;
function demo() {
let y = 20;
let x=5;
console.log(x);
console.log(y);
}
console.log(x);
demo();
}
demoFunction();
字符串
有谁能解释一下为什么我们在这段代码中重新声明了let x=5,而这段代码却显示错误?它应该显示由于词法作用域的错误。
3条答案
按热度按时间vltsax251#
从MDN's documentation for let中的第一个示例可以看出这是可以接受的。
再往下,你可以看到这句话:
let声明不能被同一作用域中的任何其他声明重新声明。
关键是“同一范围”。
从MDN's definition of scope:
JavaScript有以下几种作用域:
全球范围:在脚本模式下运行的所有代码的默认范围。
模块范围:以模块模式运行的代码的范围。
功能范围:用函数创建的作用域。
此外,用let或const声明的变量可以属于一个额外的作用域:
阻止范围:用一对花括号创建的作用域(一个块)。
示例中的两个
x
声明都在两个不同的函数作用域中,因此这是可以接受的。注意,与
var
不同,let
每次都会创建一个全新的变量。var
只会在新的 * 函数作用域 * 中创建新的变量(var
本质上是支持旧应用程序的遗留代码-不要使用它)。你也可以引用 * 不在同一作用域中,但 * 在封闭作用域中的变量。封闭作用域链称为作用域链。当引用
x
时,解释器将采用它在作用域链中找到的第一个x
。字符串
在该代码片段中,有6个不同的变量(一个
x
,两个y
s和三个z
s)。引用哪个变量取决于我在哪个范围内进行引用。解释器将采用作用域链中最近的一个。lstz6jyr2#
从ES6(2015年)开始,JavaScript引入了新功能,其中
let
和const
关键字是新添加的。在
let
和const
之前,我们有var
关键字。即使您在这里使用了var
,它也不会有问题,因为它显然在自己的范围内。在下面的代码中:
字符串
你在
demoFunction()
中使用了一个demo()
函数,为什么你会期望它抛出错误。如果你已经学习了执行块的概念。那么你就知道每个函数一旦被调用就有它自己的执行上下文,其中包含在它内部定义的变量集。因此,在demo()
函数中声明的变量x有自己的执行上下文和作用域。当函数被调用时,变量集可以在该范围内被访问,并且函数返回时,变量被销毁。因此,* 外部变量x* 永远不会知道其他函数中还有其他变量。72qzrwbm3#
你不会得到任何类型的词法作用域错误,因为用let和const关键字声明的变量是块作用域的(在严格模式下)。由于函数也是块范围的,因此在某个块中声明的变量在该函数中是可访问的。但是,每个函数都有自己独立的执行上下文,在调用堆栈中逐个调用。这两个变量有两个不同的作用域和两个不同的执行上下文,这就是为什么它没有显示任何类型的错误。
字符串