在JavaScript中,所有参数均按值传递。当函数将新值分配给参数变量时,该更改将对调用者不可见:
var obj = {a: 2}; function myfunc(arg){ arg = {a: 5}; // 注意分配是给参数变量本身 } myfunc(obj); console.log(obj.a); // 2
但是,对此类参数的(嵌套)属性所做的更改对调用者将是可见的:
var obj = {a: 2}; function myfunc(arg){ arg.a= 5; // 分配给参数的属性 } myfunc(obj); console.log(obj.a); // 5
这可以看作是通过引用进行的调用:尽管函数无法通过为其分配新值来更改调用者的对象,但它可能会使调用者的对象发生突变。
由于原始值参数(例如数字或字符串)是不可变的,因此函数无法对其进行突变:
var s = 'say'; function myfunc(arg){ arg += ' hello'; // 分配给参数变量本身 } myfunc(s); console.log(s); // '说'
当一个函数想要改变作为参数传递的对象,但又不想真正改变调用者的对象时,应该重新分配参数变量:
var obj = {a: 2, b: 3}; function myfunc(arg){ arg = Object.assign({}, arg); // 分配给参数变量,浅表副本 arg.a= 5; } myfunc(obj); console.log(obj.a); // 2
作为对参数进行就地突变的替代方法,函数可以基于参数创建一个新值,然后将其返回。然后,调用者甚至可以将其分配给作为参数传递的原始变量:
var a = 2; function myfunc(arg){ arg++; return arg; } a = myfunc(a); console.log(obj.a); // 3