function func(x = y, y = 2) {
return [x, y];
}
func(); // ReferenceError: y is not defined
func(1); // [1, 2]
如上面的代码暗示,函数参数范围中有一个隐藏的TDZ,这解释了为什么下面的代码失败:
function func(arg) {
let arg = 1; // SyntaxError: Identifier 'arg' has already been declared
}
所以函数参数应该用let
声明,但让我困惑的是:
function func(arg) {
var arg = 1;
console.log(arg); // 1
}
此代码工作正常。
为什么你可以使用var
重新声明变量? Javascript如何声明函数参数?
编辑:
我确切地知道你不能使用let来重新声明变量。这里的问题是函数参数是否使用let
声明,所以:
function func(arg) {
var arg = 1;
}
就像:
let arg; // arg parameter declares here
var arg = 1; // func body
为什么这可以毫无例外地运行?
答案 0 :(得分:3)
确实是的。看看here以获取更多示例。函数参数范围中有一个隐藏的TDZ
Javascript如何声明函数参数?
作为参数 - 请参阅here以获取逐步说明。它们既不是let
也不是var
,它们有自己的语义。引入默认初始化程序的ES6给予它们与let
中相同的TDZ限制,以捕获更多程序员错误。
为什么您可以使用
var
重新声明变量?
因为在ES5之前,重新声明变量不是错误条件,并且需要保留此行为以不破坏Web。它只能用于新功能,例如let
和const
- 或使用默认初始值设定项的参数列表,请尝试function x(bar, bar) {}
vs function x(bar, bar=1){}
。
答案 1 :(得分:1)
这并不一定与函数的论据有关。
这也会引发错误:
function func() {
var arg = 1;
let arg = 2
console.log(arg); // 1
}
func();

您无法使用let
重新声明变量,而var
并非严格:var
不会如果变量已经声明,则尝试重新声明变量。它只是分配新值。
有关let
详细信息的详细信息,请参阅this MDN page on the let
statement.
答案 2 :(得分:1)
原因在于,JavaScript社区中的人称之为"吊装"当你var arg = 1
转换为var arg;
arg = 1;
时,如果由于函数参数已经定义了var,那么编译器会尝试帮助并忽略后续重新声明而不是抛出错误......这可能是一个意外的行为,并且没有使用新的let变量声明,但是,由于向后兼容的原因,它必须保持在那里。
答案 3 :(得分:0)
let
并且随之添加了错误抛出,当您尝试声明涉及let
两次的变量时,会出现错误抛出。 var
只会替换旧值,除非已使用let
声明变量,否则不会发生这种情况。
function func(arg) {
let arg = 1; // not ok, because `let` knows that `arg` is being redeclared
}
function func(arg) {
var arg = 1; // ok, because `var` will just replace the value of `arg`
}
function func() {
let arg = 0;
var arg = 1; // not ok, because `let` declared `arg` already
}
以下是MDN for let的链接,其中说明了该功能。
答案 4 :(得分:0)
所以var
是遗留语法,理想情况下你可能想避免使用它。
而是将let
用于可以重新分配的变量,而将const
用于常量。
var
也具有全球范围,其中let
和const
仅限于其所在的范围。
答案 5 :(得分:0)
参数绑定并不完全遵循与let
声明的行为相同的行为。
1)参数绑定在var
绑定之前创建。 var
不会创建已存在的绑定,因此从来没有问题。但let
会在var
之后创建绑定。
2)在创建范围的所有产品上都存在早期错误,通常情况下,当已经存在具有相同名称的变量声明时,不会发生词法绑定。
答案 6 :(得分:-2)
如果将参数传递给func
调用,第一个示例不会将错误值抛出。
var
与let
或const
的范围不同。