【问题标题】:function arguments函数参数
【发布时间】:2009-03-19 15:29:00
【问题描述】:
function Foo(f) {
   var f = f;    
}

这里在函数内部,变量fFoo的局部变量(它有一个函数作用域),但是为什么参数列表中的变量f没有冲突呢?可能是因为它绑定在 Foo.arguments 对象内?

在其他语言中,我们不能声明与局部变量同名的参数变量。

如何解决此名称歧义?或者,您如何在方法后面引用两个不同的f 变量?

【问题讨论】:

  • 还有什么问题?
  • 隐含的问题是:名称歧义如何解决,或者您如何在方法后面引用两个不同的“f”变量。

标签: javascript scope


【解决方案1】:

JavaScript 做了几件显然不直观的事情——你感兴趣的事情叫做“提升”——JS 将 var 声明移动到函数的顶部,它们的唯一目的是保留这个变量name 作为函数作用域中的局部变量。有时,这会导致lots of weirdness。如果变量名已被保留为局部变量(例如,它是一个参数),则 var 声明将被完全删除。

JS 的另一个不直观的部分是它如何处理参数变量和arguments 对象(这有点特殊,如 Hippo 所示)。不过,这不一定是您感兴趣的 - 对于您的示例来说重要的是,参数还将变量名称声明为函数的本地变量。

所有这一切的结果是,当您拥有 var f 以及参数名称 f 时,`var f' 被删除,您的示例相当于:

function Foo(f) {
   f = f;
}

您可以在 Hippo 的示例中看到这一点,因为:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

相当于:

function foo(f) {
    var f;
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

相当于:

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    f = 10;
    console.log(f); // --> 10
    console.log(arguments); // --> [10] (!!!)
}

有关更多详细信息,请阅读 JS 规范 ECMA-262 中的 10.1.3 - 变量实例化部分(第 37 页底部)。

【讨论】:

  • "hositing" 应拼写为"hoisting"
【解决方案2】:

没有办法解决这个问题,除了重命名其中一个,或者将值存储在另一个变量中。

function foo(f) {
    console.log(f); // --> 11
    console.log(arguments); // --> array [11]
    var f=10;
    console.log(f); // --> 10
    console.log(arguments); //even this is now array [10]
}
foo(11);

【讨论】:

  • 实际上这是错误的 :D 第一次 log(f) 时它会产生 undefined,因为 js 规范会将所有 var 声明提升到函数的开头(赋值保持在同一位置)跨度>
  • @olliej:在这种情况下,f已经通过第一个参数在本地定义,实际上由于传递的值,在函数执行之前已经设置为11。跨度>
【解决方案3】:

一旦你声明了一个与旧变量同名的新变量,它就会覆盖它并且你不能同时引用这两个变量。

您应该更改参数或变量名。

【讨论】:

    【解决方案4】:

    这里的函数变量 f 是 Foo 的局部变量(它具有函数范围),但参数列表中的变量 f 的命名方式与它不冲突的原因相同,可能是因为它绑定在Foo.arguments 对象?

    不,它不受参数约束:参数只是位置参数值的数组,你不能从中得到“arguments.f”。

    按名称传递给函数的参数成为局部变量。带有参数“f”的函数中的“var f”是隐式的。

    当你在一个已经是本地的变量上声明“var f”时,什么也没有发生。您的代码与以下内容相同:

    function Foo(f)
    {
        f = f;
    }
    

    在其他语言中,我们不能声明与局部变量同名的参数变量。

    在 JavaScript 中,只要在范围块中使用了一次“var x”,那么在该块中对“x”的任何使用都是本地的。你可以愉快地在同一个范围内一次又一次地在同一个变量上声明“var”,但它什么也没做。

    【讨论】:

    • 可能是函数作用域...JS没有作用域块
    【解决方案5】:

    在 firefox 中,我注意到声明新变量并没有造成任何伤害,就好像声明不存在一样

      <script type="text/javascript">
    
      function saymessage(f) {
        alert(f);
        var f = f;
        alert(f);
        alert(this.f);
      }
      </script>
    </head>
    
    <body >
    
      <!-- Insert Body Here -->
    <button  id='link' textToShow="Hidden message text" onclick="saymessage('Hello World')">Click me </button>
    
    </body>
    

    我在第 1 次和第 2 次警报中收到“Hello World”,在第三次收到“未定义”

    【讨论】:

    • 是的,因为 this 绑定到该函数上下文中的窗口对象并且未定义,因为不存在任何声明为 window.f = ...
    猜你喜欢
    • 2018-10-02
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 2022-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多