【问题标题】:How does Javascript declare function parameters?Javascript如何声明函数参数?
【发布时间】:2018-03-23 07:21:26
【问题描述】:
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 

为什么它可以无异常运行?

【问题讨论】:

  • var 是旧语法,但 let 是新语法。这只是一个怪癖。
  • 你不应该重新声明函数参数,它们在进入函数体时已经声明了。
  • @Pointy 我认为你是唯一理解这里问题的人,也许这是因为 V8 必须与 ES5 兼容。但仍然需要与真正进入 V8 的人确认。

标签: javascript ecmascript-6


【解决方案1】:

函数参数范围内有一个隐藏的TDZ

确实如此。查看here 了解更多示例。

Javascript如何声明函数参数?

作为参数 - 请参阅here 了解分步说明。它们既不同于let,也不同于var,它们有自己的语义。 ES6 引入了默认初始化程序,为它们提供了与 let 相同的 TDZ 限制,以捕获更多的程序员错误。

为什么可以使用var 重新声明变量?

因为在 ES5 之前,重新声明变量不是错误条件,需要保留这种行为以免破坏网络。它只能针对新功能引入,例如 let 和 const - 或使用默认初始化程序的参数列表,请尝试 function x(bar, bar) {} 与 function x(bar, bar=1){}。

【讨论】:

    【解决方案2】:

    这不一定与函数的参数有关。

    这也会引发错误:

    function func() {
        var arg = 1;
        let arg = 2
        console.log(arg); // 1
    }
    
    func();

    您不能使用let 来重新声明变量,而var 没有那么严格:var 不会尝试重新声明变量,如果它已经宣布了。它只是分配新值。

    有关let 的详细信息,请参阅this MDN page on the let statement.

    【讨论】:

    • 是的,我很困惑为什么这也被否决了...(您可以添加 link to the documentation stating this though)
    • 在我的问题中,我认为参数是使用let 声明的,所以问题是为什么let arg ; var arg = 1; 应该抛出异常而不是?
    • @George:谢谢。我添加了一个链接。
    • @jerrypy:不管参数是在内部使用let 还是var 声明的。对于重新声明,重要的是变量已经声明。
    【解决方案3】:

    原因在于,JavaScript 社区中的人们在执行 var arg = 1 时将其称为“提升”,它会被翻译成 var arg; arg = 1; 但是如果 var 已经被定义为由于函数参数的原因,这里的情况下,编译器会尝试提供帮助并忽略后续的重新声明而不是抛出错误......这可能是一个意想不到的行为,并且没有遵循新的 let 变量声明,但是,出于向后兼容性的原因,它必须保留在那里。

    【讨论】:

      【解决方案4】:

      所以var 是遗留语法,理想情况下您可能希望避免使用它。

      将let 用于可重新分配的变量,将const 用于常量。

      var 也具有全局范围,而 let 和 const 仅限于它们所在的范围。

      【讨论】:

        【解决方案5】:

        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 的链接,它解释了该功能。

        【讨论】:

        • 如果你先用let声明一个变量,然后用var重新声明它,它不能替换值。 let arg; var arg = 1; 这会抛出异常。
        • 有趣,不知道,我更新了答案。
        【解决方案6】:

        参数绑定并不完全遵循与let 声明的行为相同的行为。

        1) 参数绑定在var 绑定之前创建。 var 不会创建已经存在的绑定,所以那里永远不会有问题。 let 但是在 var 之后创建绑定。

        2) 所有创建一个范围的产生式都有一个早期错误,当已经有一个同名的变量声明时,不能发生词法绑定。

        【讨论】:

          【解决方案7】:

          如果将参数传递给func 调用,第一个示例将不会抛出错误值。

          var 与let 或const 的作用域不同。

          【讨论】:

          猜你喜欢
          • 2010-12-24
          • 2012-09-29
          • 2016-07-08
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-05
          • 1970-01-01
          相关资源
          最近更新 更多