You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript数组按引用传参可改值但无法重赋值原数组的原因

核心原理

JavaScript 函数的参数传递规则是按值传递:当传入的参数是引用类型(数组、对象等)时,形参拿到的是「原始引用的地址副本」,既不是原始引用本身,也不是引用指向值的深拷贝。

为什么在函数内修改数组成员,外部数组会同步更新

把外部的myArray传入myFunction时,内部形参arr存储的地址副本,和外部myArray存储的地址指向同一块堆内存,也就是同一个数组实体。
此时调用arr.push(4)是直接修改这块内存里存储的数组内容,没有改动arr本身存储的地址值,所以内外两个引用指向的都是同一个被修改过的数组,外部打印自然能看到变化。
对应示例代码:

let myArray = [1, 2, 3];
console.log( JSON.stringify(myArray) ); // [1, 2, 3]

function myFunction(arr) {
  arr.push(4);
  console.log( JSON.stringify(arr) ); // [1, 2, 3, 4]
  return arr;
}

myFunction(myArray);
console.log( JSON.stringify(myArray) ); // [1, 2, 3, 4]

(示例配套样式,不影响逻辑:

.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

)

为什么在函数内给形参重赋值,不会影响外部数组

在函数内部执行arr = [0]时,本质是修改函数作用域内形参arr这个变量存储的地址值,让它从原来指向[1,2,3]的内存地址,改为指向新创建的[0]数组的内存地址。
这个改动只作用在函数内部的副本变量上,完全不会修改外部作用域中myArray存储的地址值,所以外部的myArray依然指向原来的[1,2,3],值不会发生变化。
对应示例代码:

let myArray = [1, 2, 3];
console.log( JSON.stringify(myArray) ); // [1, 2, 3]

function myFunction(arr) {
  arr = [0];
  console.log( JSON.stringify(arr) ); // [0]
  return arr;
}

myFunction(myArray);
console.log( JSON.stringify(myArray) ); // [1, 2, 3]

(示例配套样式,不影响逻辑:

.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

)

为什么全局作用域下直接重赋值可以生效

在全局作用域执行myArray = [0]时,操作的就是全局作用域下myArray这个变量本身,直接修改它存储的地址指向,没有经过函数参数传值时的副本拷贝环节,所以可以直接让myArray指向新的数组,重赋值自然生效。
对应示例代码:

let myArray = [1, 2, 3];
myArray = [0];
console.log(myArray); // [0]

通俗理解:把变量比作写着房间号的房卡。传参进函数相当于给内部形参复印了一张印着相同房间号的新房卡:你拿着复印房卡进房间挪动家具(修改数组/对象本身的内容),持有原房卡的人进房间当然能看到家具变了;但如果你直接把复印房卡上的房间号改成另一个新房间的号码,完全不会影响原房卡上写的房间号,持原房卡的人还是会进到原来的房间。而在全局作用域直接给myArray赋值,相当于直接涂改原房卡上的房间号,当然会生效。


内容的提问来源于stack exchange,提问作者user10869882

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:54:06