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

时间:2019-05-31 10:34:54

标签: javascript scope var let

请注意,这不是现有var vs let范围的重复项。我知道var的范围,并允许声明和区别。

但是在这种情况下,我无法证明我对letvar的不同理解。

在下面的代码中,函数foo接受名称'x'的参数,该参数具有隐式let的作用域-因为我无法在该函数内部使用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;会引发错误。

问题是:为什么在函数var中使用'foo'重新声明'x'的方法有效,但是当在全局范围中使用'{ {1}}'

1 个答案:

答案 0 :(得分:1)

var声明语法是该语言的原始语法,并且具有相当宽松的规则。 letconst声明是更新的,更严格的。无论最初如何声明变量,都无法使用letconst来重新声明变量。而且,如果用letconst声明了变量,则后续的var声明也是错误的。

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

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

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