1. 前言

JavaScript 中函数参数传递方式分为「传值传递」和「传址传递」,两者是有区别的。

2. 传值传递

函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。

var p = 2;

function f(p) {
    p = 3;
}
f(p);

p // 2

上面代码中,变量 p 是一个原始类型的值,传入函数 f 的方式是传值传递。因此,在函数内部,p 的值是原始值的拷贝,无论怎么修改,都不会影响到原始值。

3. 传址传递

但是,如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。

var obj = { p: 1 };

function f(o) {
  o.p = 2;
}
f(obj);

obj.p // 2

上面代码中,传入函数 f 的是参数对象 obj 的地址。因此,在函数内部修改 obj 的属性 p,会影响到原始值。

4. 注意事项

注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。

var obj = [1, 2, 3];

function f(o) {
  o = [2, 3, 4];
}
f(obj);

obj // [1, 2, 3]

上面代码中,在函数 f() 内部,参数对象 obj 被整个替换成另一个值。这时不会影响到原始值。这是因为,形式参数 o 的值实际是参数 obj 的地址,重新对 o 赋值导致 o 指向另一个地址,保存在原地址上的值当然不受影响。

5. 总结

JavaScript 中函数参数传递方式分为「传值传递」和「传址传递」:

  • 传值传递:参数是原始类型(数值、字符串、布尔值)
  • 传址传递:参数是复合类型(数组、对象、其他函数)