在 JavaScript 中传递值和内存消耗

Pass by value and memory consumption in JavaScript

提问人:LongHike 提问时间:6/30/2022 最后编辑:E_net4LongHike 更新时间:6/30/2022 访问量:73

问:

假设我得到了这个代码:

function MinMax(list) {
  const min = Math.min(...list);
  const max = Math.max(...list);

  return {
    min,
    max,
    list,
  };
}

const massiveList = [
  1,
  // supposedly a gazillion
  // integer values
  10000000,
];

const minMax = MinMax(massiveList);

const minMaxList = minMax.list;

console.log('min              ', minMax.min);
console.log('max              ', minMax.max);
console.log('minMaxList length', minMaxList.length);

这是我的问题:由于参数在 JavaScript 中是通过值传递的,这是否意味着,在代码中将 minMax.list 分配给 minMaxList 的那个点之后,堆内存中存在原始 massiveList 的三个副本?

JavaScript 按值传递

评论

0赞 Nina Scholz 6/30/2022
不。您只有一个大型数组和对它的引用。
0赞 LongHike 6/30/2022
但是,例如,这里 javascripttutorial.net/javascript-pass-by-value 它说“在 JavaScript 中,所有函数参数总是按值传递的。这意味着 JavaScript 将变量的值复制到函数参数中。因此,数组必须至少存在两个副本。虽然不确定第三个。
0赞 Nina Scholz 6/30/2022
不。在 JavaScript 中,只有原始值按值传递。所有其他的,如数组(静止对象)、对象和函数都是通过引用传递的。您可以通过在移交给函数后更改数组并更改函数内部的值来证明它。外部数组(原始引用)具有相同的更改。
0赞 Jaood_xD 6/30/2022
显然是的。Spread 运算符从初始数组中创建新数组,因此垃圾回收器的不可预测性,您将拥有大量数组的最多 3 个不同副本。
1赞 Jaood_xD 6/30/2022
@NinaScholz是这样。已经完成了一个快速脚本,可以签出和检查函数内部。每次我调用它时,它都会上升,并将数组扩展为参数。process.memoryUsage().heapUsedfunction f(...arr)f

答:

2赞 Nick Vu 6/30/2022 #1

您可以尝试以下带有参考值的演示

const massiveList = [
  1,
  // supposedly a gazillion
  // integer values
  10000000,
];

const testReference = (list) => {
   console.log(list === massiveList) //true
}

testReference(massiveList)

在您的情况下,并且是相同的参考,这意味着任何修改也将应用。listmassiveListlistmassiveList

...list表示您已将原始列表克隆到另一个将在内存中新分配的列表。

下面的演示是显示新列表的参考值发生了变化,所以这就是结果的原因false

const massiveList = [
  1,
  // supposedly a gazillion
  // integer values
  10000000,
];

const testReference = (list) => {
  const newList = [...list]
  console.log(list === newList) //false
}

testReference(massiveList)

评论

0赞 LongHike 6/30/2022
谢谢,我没有考虑过检查对象相等性。这是一个非常简单而优雅的解决方案,可以找出对象的“化身”。