JavaScript 中所有函数的参数都是按值传递的

本文地址:kamal

JavaScript 中所有函数的参数都是按值传递的

当参数是值类型的时候

function changeStuff(num){
    num = num * 10;
}
var num = 10;
changeStuff(num);

alert(num);//10

可以看到当函数参数是值类型的时候在函数内部改变变量的值,不会在函数作用域外表现出来,说明函数参数是传值的方式传入函数内部。

当函数参数是Object类型的时候

function changeStuff1(obj1){
    obj1.item = "changed";
}

var obj1 = new Object();
obj1.item = "unchanged";

changeStuff1(obj1);
alert(obj1.item); //changed

这时obj1内的item的值在函数之外表现出来了,如果是传值的话,函数内部改变变量的值应该不会影响到外部的obj1啊。难道对Object类型的参数传的是传引用? 再看第三个例子

function changeStuff2(obj2){
    obj2 = {item:"changed"};
}

var obj2 = new Object();
obj2.item = "unchanged";

changeStuff2(obj2);
alert(obj2.item);//unchanged

《JavaScript高级程序设计》一书中就解释到这里就说已经证明了“ECMAScript 中所有函数的参数都是按值传递的”。可是我还是不能理解为什么第二个和第三个例子会有不一样的结果。又找了一些函数传参数的解释[1]

传值   
 是把实参的值赋值给行参   
 那么对行参的修改,不会影响实参的值 

传地址   
 是传值的一种特殊方式,只是他传递的是地址,不是普通的如int   
 那么传地址以后,实参和行参都指向同一个对象 

传引用   
 真正的以地址的方式传递参数   
 传递以后,行参和实参都是同一个对象,只是他们名字不同而已   
 对行参的修改将影响实参的值

在第二个例子中,obj1传入函数 changeStuff1 时,changeStuff1函数内部变量 obj1是一个新的内存变量,只是期指向旧的对象值,所以改变对象中item的值会在函数外部表现出来。

在第三个例子中obj2传入函数 changeStuff12时,changeStuff2函数内部变量 obj2是一个新的内存变量,依旧期指向旧的对象值,但在函数内部又给内部的obj2变量重新赋值,使其指向一个新的对象,所以改变对象中item的值不会影响函数外部的obj2对象。

最后得出结论,JavaScript 中所有函数的参数都是按值传递的 ,只是对于Object类型来说,这个值本身就是一个指向Object对象的地址。最后给出完整的测试函数[2]

function changeStuff(num, obj1, obj2)
{
    num = num * 10;
    obj1.item = "changed";
    obj2 = {item: "changed"};
}

var num = 10;

var obj1 = new Object();
obj1.item = "unchanged";

var obj2 = new Object();
obj2.item = "unchanged";

changeStuff(num, obj1, obj2);
alert(num); //10
alert(obj1.item); //changed
alert(obj2.item); //unchanged

[1] 传值和传引用、传地址的区别是什么?

[2] Is JavaScript is a pass-by-reference or pass-by-value language?

//20141205 append
几个例子用相同的变量名,有误导之嫌,起码函数参数可以用别的名称

作者:Yukun

前端工程师