为什么添加默认参数值会改变修改参数时的行为?

3

第一部分是:

var a = 1;

function fn2(a) {
  arguments[0] = 20;
  var a = 22;
  console.log(a);
  console.log(arguments[0]);
}
fn2(a);

第二部分是:

var a = 1;

function fn2(a, b = 100) {
  arguments[0] = 20;
  var a = 22;
  console.log(a);
  console.log(arguments[0]);
}
fn2(a);

我能理解为什么在第一段代码中,最终将输出22和22作为arguments[0]a,因为它们实际上都指向参数a。然而,在第二段代码中(添加了另一个参数b),最终输出的是22和20。我猜这与额外的参数b有关,并查找了一些帖子。在MDN中,我找到了以下内容:

当非严格模式的函数包含rest、default或解构参数时,arguments对象中的值不会跟踪参数的值。相反,它们反映了调用函数时提供的参数。

以下是来自MDN的示例代码:

function func(a = 55) { 
  arguments[0] = 99; // updating arguments[0] does not also update a
  console.log(a);
}
func(10); // 10

我知道这句话的意思,但是我的问题和这个例子不同。

  1. 在 MDN 的例子中,指向 arguments[0] 的是有默认值的 a,而在我的问题中,没有指向 arguments[0]b 有一个默认值。这是两种不同的情况。

  2. 我还在控制台上调试,并发现:

enter image description here

为什么这里有两个 a?一个在块级作用域中,而另一个在局部作用域中。那么哪一个才是参数 a?另一个不是参数的 a 来自哪里?


@CertainPerformance 请再看一遍 - Chor
因为一个'a'被传递作为参数,被视为局部变量,而另一个是你在函数内使用var创建的全局变量。这就是为什么有两个a的原因。 - dharmendra vaishnav
@dharmendra vaishnav 在函数内部创建的变量也应被视为局部变量。在第一段代码中,只有一个 a。为什么? - Chor
1个回答

1
在 MDN 的例子中,指向 arguments[0] 的 a 有一个默认值,而在我的问题中,不指向 arguments[0] 的 b 有一个默认值。 这是两种不同的情况。
如果至少存在一个rest/default/destructured参数,则不对arguments的任何索引进行分配都不会导致关联变量的更改,或者没有rest/default/destructured参数,那么对arguments的任何索引的所有分配都将导致关联变量的更改。
要么arguments的每个索引都会改变其关联的变量,要么都不会。 因此,即使只有 b(arguments[1])具有默认赋值,当 b 具有默认赋值时,对 arguments[0] 的更改也将导致对 a 的更改。
为什么这里有两个a?一个在块中,另一个在本地。那么哪一个才是实际的参数a呢?还有另一个a(不是参数),它来自哪里?
我很确定Chrome调试器只是因为你已经在作用域中有一个参数a时,你又声明了一个var a而感到困惑。变量会出现在“块”部分,当它们是:
(1)在函数顶层上声明(使用constletvar),或者
(2)在非函数块内使用constlet声明
a已经存在于作用域中时,在a前面加上var是完全多余的。

但是在第二个代码段中,当b有默认赋值时,对arguments[0]的更改不会导致a的更改。它们不会一起改变。@CertainPerformance - Chor
1
@Chor — 是的。这就是您引用的材料所说的:“当一个非严格函数包含rest,default或解构参数时,参数对象中的值不会跟踪参数的值。相反,它们反映了调用函数时提供的参数”。 - Quentin
但是另一个问题是为什么在第二个代码段中存在2个a,而在第一个代码段中只存在一个a?在图片中,我认为局部变量中的a是初始参数a,它一开始就保持与arguments[0]相同。然后arguments[0]变成了20。由于失去了跟踪,这里的a将仍然保持其值(1),但是块中的a怎么样呢?它从哪里来? - Chor
当存在一个变量与参数同名时,该变量不会影响参数。如果是这样,为什么代码块中还有一个名为 a 的变量? - Chor
@Chor 我相信Chrome调试器只是因为你在作用域中已经有一个参数a的情况下又声明了var a,所以出现了混淆。这很可能是一个bug。 - CertainPerformance
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接