JavaScript中的词法作用域未显示错误

b1uwtaje  于 2023-08-02  发布在  Java
关注(0)|答案(3)|浏览(85)

有谁能解释一下为什么我们在这段代码中重新声明了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,而这段代码却显示错误?它应该显示由于词法作用域的错误。

vltsax25

vltsax251#

MDN's documentation for let中的第一个示例可以看出这是可以接受的。
再往下,你可以看到这句话:
let声明不能被同一作用域中的任何其他声明重新声明。
关键是“同一范围”。
MDN's definition of scope
JavaScript有以下几种作用域:
全球范围:在脚本模式下运行的所有代码的默认范围。
模块范围:以模块模式运行的代码的范围。
功能范围:用函数创建的作用域。
此外,用let或const声明的变量可以属于一个额外的作用域:
阻止范围:用一对花括号创建的作用域(一个块)。
示例中的两个x声明都在两个不同的函数作用域中,因此这是可以接受的。
注意,与var不同,let每次都会创建一个全新的变量。var只会在新的 * 函数作用域 * 中创建新的变量(var本质上是支持旧应用程序的遗留代码-不要使用它)。
你也可以引用 * 不在同一作用域中,但 * 在封闭作用域中的变量。封闭作用域链称为作用域链。当引用x时,解释器将采用它在作用域链中找到的第一个x

// Global scope (0)
let x = 0;
let y = 0;
let z = 0;
{ // Block scope (1) start
  let y = 1;
  let z = 1;
  { // Block scope (2) start
    let z = 2;
    console.log(`x is in scope ${x}`); // 0
    console.log(`y is in scope ${y}`); // 1
    console.log(`z is in scope ${z}`); // 2
  } // Block scope (2) end
  console.log(`x is in scope ${x}`); // 0
  console.log(`y is in scope ${y}`); // 1
  console.log(`z is in scope ${z}`); // 1
} // Block scope (1) end
console.log(`x is in scope ${x}`); // 0
console.log(`y is in scope ${y}`); // 0
console.log(`z is in scope ${z}`); // 0

字符串
在该代码片段中,有6个不同的变量(一个x,两个y s和三个z s)。引用哪个变量取决于我在哪个范围内进行引用。解释器将采用作用域链中最近的一个。

lstz6jyr

lstz6jyr2#

从ES6(2015年)开始,JavaScript引入了新功能,其中letconst关键字是新添加的。
letconst之前,我们有var关键字。即使您在这里使用了var,它也不会有问题,因为它显然在自己的范围内。
在下面的代码中:

function demoFunction() {
    let x = 10; 
  
    function demo() {
      let y = 20; 
      let x=5;
      console.log(x); 
      console.log(y); 
    }
    console.log(x); 
    demo();
  }
  
  demoFunction();

字符串
你在demoFunction()中使用了一个demo()函数,为什么你会期望它抛出错误。如果你已经学习了执行块的概念。那么你就知道每个函数一旦被调用就有它自己的执行上下文,其中包含在它内部定义的变量集。因此,在demo()函数中声明的变量x有自己的执行上下文和作用域。当函数被调用时,变量集可以在该范围内被访问,并且函数返回时,变量被销毁。因此,* 外部变量x* 永远不会知道其他函数中还有其他变量。

72qzrwbm

72qzrwbm3#

你不会得到任何类型的词法作用域错误,因为用let和const关键字声明的变量是块作用域的(在严格模式下)。由于函数也是块范围的,因此在某个块中声明的变量在该函数中是可访问的。但是,每个函数都有自己独立的执行上下文,在调用堆栈中逐个调用。这两个变量有两个不同的作用域和两个不同的执行上下文,这就是为什么它没有显示任何类型的错误。

function demoFunction() {
    // Variables declared here is accessible within demoFunction scope.
    let x = 10; 
  
    function demo() {
      let y = 20; 
      // This variable here is accessible within demo scope.
      let x=5;
      console.log(x); 
      console.log(y); 
    }
    console.log(x); 
    demo();
  }
  
  demoFunction();

字符串

相关问题