所有语言均按值传递,区别在于“值”的含义:基本类型传数据副本,引用类型传地址副本;修改对象属性影响外部,但重赋值形参仅改变副本指向。

函数参数传递不是“传值还是传引用”的二选一问题,而是统一按值传递——但这个“值”本身含义不同:基本类型传的是数据本身,引用类型传的是内存地址的副本。
基本类型:传的是数据副本,改了也不影响外面
int、string、boolean 等基本类型在栈中直接存值。传参时,系统复制一份值给形参,形参和实参完全独立。
- 形参修改只是改了副本,原变量毫发无损
- 哪怕在函数里把参数从 5 改成 100,调用方的变量仍是原来的值
- 本质是“隔离操作”,就像拿一张复印件涂改,原件不会变
引用类型:传的是地址副本,能改内容但改不了指向
对象、数组、函数等引用类型,变量本身存的是堆中对象的地址。传参时复制的是这个地址,不是对象本身。
- 通过形参修改对象属性(如 obj.name = 'x')或数组元素(如 arr[0] = 99),外部可见——因为地址没变,操作的是同一块堆内存
- 但若在函数内重新赋值形参(如 obj = { } 或 arr = [ ]),只是让形参指向新地址,原变量仍指着老地方
- 关键看有没有执行 = 操作:没赋值 → 改内容有效;赋了值 → 只影响副本
所有语言都按值传递,区别只在“值是什么”
Java、JavaScript、Python 等主流语言,参数传递机制底层都是“按值传递”。所谓“引用传递”的错觉,来自对“地址值”和“引用本身”的混淆。
- Java 没有真正的引用传递,连 String 都是不可变对象,传的是字符串对象地址的副本
- JavaScript 中 null、undefined 是基本类型,但它们也是值;Object.assign 或展开运算符复制的是浅层属性,不改变地址传递的本质
- Python 的“可变/不可变”分类,实际对应的就是:不可变对象一改就新建,可变对象允许原地修改——但传的始终是对象引用
写代码时真正该盯住的两个动作
不必纠结语言叫它什么,只需盯住函数体内是否发生了这两件事:
- 读取或修改对象内部状态(如 obj.key = val、arr.push(x)、map.set(k,v))→ 外部对象同步变化
- 对形参变量重新赋值(如 param = {}、param = []、param = new Date())→ 仅切断当前形参与原对象的联系,不影响调用方











