JavaScript函数参数始终按值传递:基本类型传数据副本,修改不影响外部;引用类型传地址副本,可修改属性但重赋值不改变外部对象。

JavaScript 中的函数定义和参数传递看似简单,但细节决定行为是否符合预期。核心在于:函数是值,参数传递始终是“值传递”,但这个“值”可能是基本类型的实际数据,也可能是引用类型的地址副本。
function 基本定义方式
最常用的是函数声明(Function Declaration):
function sayHello(name) {
return 'Hello, ' + name;
}
它会被提升(hoisted),可在定义前调用。另外还有函数表达式(Function Expression):
立即学习“Java免费学习笔记(深入)”;
const sayHi = function(name) {
return 'Hi, ' + name;
};
这种不会被提升,必须先定义再调用。箭头函数(Arrow Function)语法更简洁:
const greet = (name) => 'Hey, ' + name;
参数传递:值传递,但分两类
JavaScript 没有“引用传递”。所有参数都是按值传递——但值的内容取决于类型:
- 基本类型(string、number、boolean、null、undefined、symbol、bigint):传的是实际值的副本。函数内修改不影响外部变量。
- 引用类型(object、array、function、class 实例等):传的是指向内存地址的副本。函数内通过该地址修改对象属性,外部可见;但若直接赋新对象,则断开连接,不影响外部。
例如:
let x = 10;
let obj = { a: 1 };
function change(x, obj) {
x = 20;
obj.a = 2;
obj = { b: 3 }; // 重赋值,只改本地副本
}
change(x, obj);
console.log(x); // 10(未变)
console.log(obj); // { a: 2 }(属性变了,但没变成 {b:3})
参数处理的实用技巧
现代 JavaScript 提供了更灵活的参数控制方式:
- 默认参数:function fn(a = 'default') { ... }
- 剩余参数(...args):收集不定数量的实参为数组,替代 arguments 对象。
- 解构参数:function getUser({ name, age }) { return `${name} is ${age}`; },调用时传对象即可。
- 避免 mutation:如需修改数组或对象,优先用展开运算符或 Object.assign 创建新值,而非直接修改入参。
小结:关键不是“传值还是传引用”,而是“传的是什么值”
记住:函数接收的永远是一个值。对基本类型,这个值就是数据本身;对对象,这个值是内存地址的拷贝。理解这点,就能预判哪些修改会对外部产生影响,哪些不会。写函数时,明确输入是否可变、是否应返回新数据,代码会更可靠。










