JavaScript值传递机制下的堆内存占用问题解析
示例代码
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的三份副本?
解答
结论:不会。堆内存中自始至终仅存在1份massiveList对应的数组实体,不存在三份副本。
很多人对JS的「按值传递」规则存在误解,理清整个执行流程的内存逻辑就能得到明确答案:
- JS中所有变量的传参、赋值都遵循按值传递规则,但要区分传递的值的类型:如果是原始类型(数字、字符串、布尔值等),拷贝的是值本身;如果是引用类型(数组、对象等),拷贝的「值」是指向堆内存实际实体的内存地址,不会把堆中存储的整个对象/数组完整拷贝一份。
- 逐环节梳理内存状态:
- 声明
massiveList时,引擎会在堆内存创建唯一一份数组实体,栈内存中的massiveList变量存储的是指向这份数组的内存地址。 - 调用
MinMax(massiveList)时,形参list拿到的是拷贝后的地址值,和massiveList指向堆中同一份数组,不会生成新的数组副本。 - 函数返回的对象中挂载的
list属性,存储的还是同一个地址,外部变量minMax拿到返回对象后,minMax.list依然指向堆中的原数组。 - 执行
const minMaxList = minMax.list时,只是把地址值再拷贝了一份赋值给minMaxList,指向的还是堆里那同一份数组。
- 声明
整个流程里,栈内存中确实会存储多份相同的内存地址,但堆内存里从始至终只有1份原始数组的实体,连第二份副本都不会生成,更不存在三份副本的情况。
内容的提问来源于stack exchange,提问作者LongHike
相关产品推荐
相关产品推荐

