猿问

为什么在JavaScript中对数组“B”的更改会传播到数组“A”?

我创建了一个名为“alphabet”的常量,并将其分配给包含字母表前 5 个字母的数组。然后,我想要一个函数,该函数将向数组中的每个字符添加一个数字,以枚举它们。但是,我不希望修改原始“字母表”数组中的值,因此我在枚举函数中创建了一个“temp”变量,并且只对其进行了更改。但是,我对“temp”所做的任何更改都扩展到“字母表”。我不明白为什么,我想阻止这种情况发生。

const alphabet = ["a", "b", "c", "d", "e"];


function alphaPosition(seq) {

  //'temp' gets 'seq' to avoid making changes directly on the provided argument.

  let temp = seq;

  //adds indexes to each element in the 'temp' array:

  for (let i = 1; i <= temp.length; i++) {

    temp[i - 1] = temp[i - 1] + i;

  }

  return temp;

}


console.log(

  "Step 1. 'alphabet' array before running the 'alphaPosition' function:"

);

console.log(alphabet);

console.log(

  "Step 2. This is the final value of 'temp' in 'alphaPosition' after running the function. An index has been added to every element in the array, as expected:"

);

console.log(alphaPosition(alphabet));

console.log(

  "Step 3. Here's the 'alphabet' array after running 'alphaPosition'. Indexes have also been added to every element, despite not modifying the function argument directly:"

);

console.log(alphabet);

输出:


/*

-> Step 1. 'alphabet' array before running the 'alphaPosition' function:

-> ["a", "b", "c", "d", "e"]

-> Step 2. This is the final value of 'temp' in 'alphaPosition' after running the function. An index has been added to every element in the array, as expected:

-> ["a1", "b2", "c3", "d4", "e5"]

-> Step 3. Here's the 'alphabet' array after running 'alphaPosition'. Indexes have also been added to every element, despite not modifying the function argument directly:

-> ["a1", "b2", "c3", "d4", "e5"]

*/

为什么对“临时”的更改会传播为“字母表”?我希望,既然我把“字母表”定义为一个常量,那么甚至不应该修改它。此外,我从不在函数中对其进行更改。我只用它来定义“温度”。有没有办法防止这些传播的发生?


为什么使用中间变量来避免对原始数字进行更改,而不是数组?


如果对此有任何帮助或澄清,我将不胜感激。我已经将我的代码添加到这个CodePen中,以防你想调整它或尝试更多。提前感谢您的任何帮助。


慕容森
浏览 101回答 2
2回答

DIEA

这是关于分配在脚本中的工作方式。给定以下代码:const a = { foo: "bar" };const b = a;变量和两者都指向同一对象。这意味着内存中只有一个对象,当您尝试使用对象访问对象时,将反映对象指向的可变,反之亦然。例如:ababconst a = { foo: "bar" };const b = a;a.foo = "baz";console.log(a);console.log(b);展开代码段那么现在,我们如何使这种情况不会发生呢?为此,我们可以将 的浅副本分配给 。这可以通过几种不同的方式完成,下面使用传播运算符(...):abconst a = { foo: "bar" };const b = { ...a };a.foo = "baz";console.log(a);console.log(b);展开代码段所以现在,内存中有两个不同的对象。你会注意到我称之为浅层复制,这很重要:如果你有深层对象,你需要深度复制才能完成同样的解耦。如何在您的特定情况下解决此问题:针对您的特定情况的 TLDR 是,您的临时变量应该是数组的浅副本,而不是对现有数组的引用:let temp = [...seq];

GCT1015

这似乎是重复的。潜在的答案就在这里。我在下面解释原因:对于字符串和数字,javascript 似乎是按值传递的,而数组等对象是按引用传递的。这意味着在你的第一个例子中;该函数正在获取对原始数组的引用,当您这样做时,temp实际上只是一个指向传入的原始对象的指针。在这种情况下,当您修改温度时,情况就是这样;它实际上是在修改字母表。let temp = seqalphabet按值传递只是将值发送到函数,因此原始变量与数字示例中的变量相同。为了获得预期的结果,您需要制作数组的深度副本,例如 .let temp = deepCopy(seq)我认为使用可能只是用户知道不要修改它的语法,一些编辑器不会让你在代码中重新修改const,但在这种情况下,它以迂回的方式发生。const
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答