问题 javascript函数中是否允许使用相同的变量和参数名称?


作为一个例子,我允许使用相同的变量和参数?我可以遇到什么问题?

示例代码

function mytask(name,title){
            var name = name;
            var title = title;
            var showalert = ("Hi " + name + " your job title is " + title);
            console.log(showalert);
            return showalert;
        }

document.write(mytask("dan", "administrator"));

10169
2018-06-19 23:05


起源

你为什么要这样做?为什么不直接使用参数值? - Iain
实际上没有必要声明新变量来接收参数值。您可以直接使用参数变量。 - Michael Berkowski
将变量重新声明为同一名称的唯一原因可能是提供默认值: var name = name || 'Jeff'; (或者可能, name = name ? name : 'Jeff';),但仅限于参数的可选项。 - David Thomas
@PeanutsMonkey:只是为了踢,这是一个演示: JS小提琴:http://jsfiddle.net/davidThomas/w4VJt/ 显示我能想到的唯一原因;虽然注意到了 var 不需要。 - David Thomas
因为它已被定义为传递给函数的参数/参数。 - David Thomas


答案:


那么在javascript中你可以认为,范围被定义为我的大括号: { 和 },并且范围内的变量可以重新定义,所以看看:

function x(){
  var name=3;
  var name=4;
  console.log(name); // output is: 4
}
x();

但这只是半真的,实际上发生的是解释器遍历代码,并移动所有 var 声明到开头,而他们被分配了 undefined (并且所有参数都是从堆栈中定义并从中获取的),然后您编写的代码将运行。所以任何 var 在第一个之后被简单地忽略了。你写的代码等于:

function mytask(name,title){
   var name = arguments[0];
   var title = arguments[1];
   name = name;
   title = title;
   var showalert = ("Hi " + name + " your job title is " + title);
   console.log(showalert);
   return showalert;
}

document.write(mytask("dan", "administrator"));

所以你的减速和分配是多余的。无论如何 - 范围没有变化,没有别的东西会有所不同。

编辑

解释器遍历你的代码,执行任何东西,任何 var x = y; 声明将分裂成 var x = undefined; 和 x=y;。而且 var x = undefined; 将被移动到代码的顶部。而且 x=y; 将与原始陈述在同一个地方。如果您不了解堆栈的内容,请不要理会,这就是编译器将函数调用转换为汇编的方式 - 如果您有时间,则值得了解;但不是重要的事情。

无论如何 - 在这些更改之后,可能会进行一些优化,执行生成的代码。这不是你写的代码,而是一个相同的代码。你在重新定义参数时指出的是这种转换变得可见的边缘情况。


5
2018-06-19 23:32



你能详细说明你的意思吗?“将所有var语句移动到开头,同时为它们分配一个未定义的(并且所有参数都是从堆栈定义并从中获取的),然后你编写的代码将运行”? - PeanutsMonkey
@PeanutsMonkey请参阅编辑 - Ramzi Kahil
好的只是为了清楚地明白你的意思我会反刍。如果我误解了,请告诉我。如果我有我的问题中的函数,其中参数和变量共享相同的声明,你的意思是说解释器将拆分 name = name 成 name = undefined 和 name = name。是对的吗? - PeanutsMonkey
我不明白堆栈的一点,但肯定会掩盖它。但我并不明白你的意思 Anyway - just after those changes, and maybe some optimizations are made。你指的是什么变化?进行了哪些优化?这些是翻译吗? - PeanutsMonkey
@PeanutsMonkey看一看 这个 或者只是搜索 hoisting  - 这就是我所谈论的转型的正式名称。 - Ramzi Kahil


这样考虑一下:

var name = name;

唯一的办法 name 可以设置为的值 name 是的 name 是 已经 定义。如果,没有必要做两次 name 已经拥有你想要的价值。


2
2018-06-19 23:16





好吧,我想一些解释不会受到伤害。 )

首先,所有函数的参数都已声明为此函数的本地。 (它有点复杂,但让我们说这个解释涵盖了大部分内容)。所以再次定义它们是没有用的:它们不会在它之后成为“更本地化”。 ))

其次,可以写 var name = name 在...内 function(name) 出于同样的原因,为什么可以写 var name = 123; var name = 345;。第二 var 将被默默地忽略。

如果你写 var name = 123; var name = name;,你只会浪费一些按键 - 再次,它和你写的一样 name = name; 你代码中的某个地方。 )

而那,顺便说一下,弄乱了 arguments。看到, name 实际上是其元素的别名。


2
2018-06-19 23:18



你是什​​么意思“第二个var将被默默地忽略”以及解释弄乱了 arguments? - PeanutsMonkey
您是否希望我更详细地解释吊装的工作原理? - raina77ow
@ raina77ow这会在“严格”模式下工作吗? - user
@buffer什么是“这个”? - raina77ow
在其范围内重新分配函数参数,例如 function change(a) { a = 2}。另见 stackoverflow.com/a/6433583/781695 - user


当然你可能会遇到问题。看看这个。

function mytask(name,title){
            console.log(name);
            console.log(title)
            var name = "oops";
            var title = "rawr";
            console.log(name);
            console.log(title)
}

mytask("dan", "administrator");

打电话,除了非常混乱 console.log(name); 给我们两个不同的结果(因为我们重新定义了它)。这是允许的,但这不是一个好主意。

编辑:有趣的是(我不知道这一点),做上面的搞砸隐含了 arguments[] 阵列也是如此。例如,做:

for( var i = 0; i < arguments.length; ++i ) {
    console.log(arguments[i]);
}

我们的函数内部(重新分配后)仍在输出 oops 和 rawr。显然,这是一个糟糕的坏主意。


1
2018-06-19 23:10





实际上没有理由这样做。将它们传递给函数后,它们将被初始化,您可以使用它们而无需将它们重新分配给其他变量。


1
2018-06-19 23:10





您可以使用与参数同名的变量,因为值无论如何都是相同的,除非具有相同名称的变量具有与参数不同的值。


1
2018-06-19 23:10