← 返回题目列表

JavaScript 参数传递是按值还是按引用?

高频 中等 第 12 / 29 题 更新于 2026/07/29
JavaScript参数传递引用类型

简化版

JavaScript 参数传递本质上都是按值传递:原始类型传的是值的副本,对象类型传的是“引用值”的副本。函数内修改对象属性会影响外部对象,但把参数重新赋值为新对象不会改变外部变量绑定。

详细版

示例:

function change(obj) {
  obj.name = 'Bob';
  obj = { name: 'Carol' };
}

const user = { name: 'Alice' };
change(user);
console.log(user.name); // Bob

很多人说“对象按引用传递”,这容易误导。 更准确的说法是:对象变量里保存的是引用值,传参时复制了这个引用值。 因此函数内能通过这份引用找到同一个对象并改属性,但不能通过重新给参数赋值来改变外部变量指向。

完整版教学

一、先区分变量、值和对象

JavaScript 变量不是盒子里直接装对象。 对原始类型,变量保存具体值。 对对象类型,变量保存能找到对象的引用值。

let a = 1;
let b = { count: 1 };

可以简化成:

a -> 1
b -> 引用地址 -> { count: 1 }

这个模型不是引擎真实内存图,但足够解释面试题。 关键是:变量绑定和值是两回事,对象本体又是另一回事。

二、函数传参时复制的是参数值

调用函数时,实参的值会赋给形参。 如果实参是原始值,就复制原始值。 如果实参是对象引用值,就复制这个引用值。

function add(x) {
  x = x + 1;
}

let n = 1;
add(n);
console.log(n); // 1

数字例子很好理解:n 的值 1 被复制给 x。 函数里把 x 改成 2,不会影响外部 n。 这是按值传递的基本表现。

三、对象属性修改为什么能影响外部

对象传参时复制的是引用值。 形参和外部变量暂时指向同一个对象。 所以通过形参修改对象属性,会改到同一个对象本体。

function update(user) {
  user.age = 20;
}

const u = { age: 18 };
update(u);
console.log(u.age); // 20

流程如下:

u ----\
      -> { age: 18 }
user -/

user.age = 20
      -> { age: 20 }

这就是很多人误以为“对象按引用传递”的来源。 但只说这半句会解释不了重新赋值的行为。

四、重新赋值参数不会改变外部变量

如果在函数里把形参改成另一个对象,只是让形参指向新对象。 外部变量仍然指向原对象。 这是判断“按值传递”的核心例子。

function reset(user) {
  user = { age: 0 };
}

const u = { age: 18 };
reset(u);
console.log(u.age); // 18
操作是否影响外部对象原因
user.age = 20改同一个对象的属性
user = { age: 0 }只改形参绑定
u = { age: 0 }改外部变量自己的绑定

这个表格能把“改对象”和“改变量指向”分开。

五、数组也是对象,规则完全一样

数组传参没有特殊规则。 pushsplice 会修改同一个数组对象。 重新赋值为新数组不会改变外部变量。

function demo(list) {
  list.push(3);
  list = [9, 9, 9];
}

const arr = [1, 2];
demo(arr);
console.log(arr); // [1, 2, 3]

这个例子里 push 生效,list = [...] 不影响外部。 如果希望函数不产生副作用,可以返回新数组,而不是直接改入参。

六、工程里要关注可变性和副作用

理解参数传递规则后,工程重点是控制副作用。 函数如果会修改传入对象,应在命名、文档或类型上明确表达。 不希望外部被影响时,可以浅拷贝或深拷贝后再操作。

function rename(user, name) {
  return { ...user, name };
}

记忆钩子:JS 传参复制的是“格子里的值”;对象变量格子里放的是引用值,所以能改对象,不能改外部变量格子。

React、Redux 等状态管理里强调不可变更新,正是为了避免这种共享对象修改带来的状态难追踪。

七、常见误区与追问

  • 误区:对象在 JavaScript 中是按引用传递。 更准确是引用值按值传递,形参拿到的是引用值副本。
  • 误区:函数里改对象属性和重赋值参数是一回事。 前者改对象本体,后者改形参绑定。
  • 误区:数组有不同的传参规则。 数组也是对象,和普通对象遵循同一套规则。
  • 追问:为什么 push 会影响外部数组? 形参和外部变量引用同一个数组对象,push 修改的是对象本体。
  • 追问:如何避免函数修改外部对象? 使用拷贝、不可变更新或冻结对象,并约定函数返回新值。
  • 追问:浅拷贝能完全避免影响吗? 不能,浅拷贝只复制第一层,嵌套对象仍可能共享引用。

八、加强记忆

这题的稳定答法是:JavaScript 只有按值传递;对象变量的值恰好是引用。先用原始类型说明形参重赋值不影响外部,再用对象属性修改和对象重赋值对比,最后补数组同理和副作用控制。