Javascript ES6 'let' 和 'var' - 参数名称与重新声明的变量匹配的函数内部的意外行为

Javascript ES6 'let' and 'var' - unexpected behavior inside function with argument name matching redeclared variable

请注意,这不是现有 var 与 let 作用域的副本。我知道 var 和 let 声明的范围和区别。

但在下面的情况下,我无法证明我对 letvar 差异的理解。

在下面的代码中,函数 foo 接受具有隐式 let 范围的名称 'x' 的参数 - 因为我无法在其中使用 let 重新声明相同的变量名称函数(取消注释函数中的最后一行 foo 将抛出 JS 错误)

"use strict";

function foo(x) {
    console.log('Inside function x:', x);
    var x = 30; // 'x' redeclared overwriting argument/parameter 'x'
    console.log('Redeclared x:', x);
    // let x = 400; // uncommenting this line throws error even if you remove 'var x = 30;'
}

foo(100);
// global
let y = 100;
console.log('y:', y);
// var y = 300;

执行上面两行注释掉的代码效果很好,你可以看到输出为:

Inside function x: 100      index.js:4 
Redeclared x: 30            index.js:6
y: 100                      index.js:13

取消注释最后一行 // var y = 300; 将引发错误。

问题是:为什么在函数 foo 中使用“var”重新声明 'x' 有效,但在 'y' 时抛出错误使用“var

在全局范围内重新声明

var 声明语法是该语言的原创语法,具有相当宽松的规则。 letconst 声明更新更严格。你不能 re-declare 带有 letconst 的变量,无论它们最初是如何声明的。如果用 letconst 声明变量,则随后的 var 声明也是错误的。

通过 letconst 的声明将不允许在声明之前引用变量;这就是为什么您会收到第一个示例中提到的错误的原因。也就是说,

console.log(x);
let x = 0;

是一个错误,因为在声明之前引用了x