function foo(x) { x.push(4); console.log(x); //1,2,3,4 x = [4, 5, 6]; x.push(7); console.log(x);//4,5,6,7 } var a = [1, 2, 3]; foo(a); console.log(a);//1,2,3,4
在传递a的时候,其实是将引用a的一个复本赋值给x,而a仍然指向x,在方法中,我们可以通过x来改变数组的值,然后重新赋值x=[4,5,6],但这病不影响a的指向
所以我们不能通过引用x来更改引用a的指向,只能更改a和x共同指向的值
如果要改变原值,就必须改变x指向的数组,而不是为x赋值一个新的数组,例如:
function foo(x) { x.push(4); console.log(x); //1,2,3,4 x.length = 0; x.push(4, 5, 6,7); console.log(x);//4,5,6,7 }
请记住,我们无法自行决定使用值复制还是引用复制,一切由值的类型来确定。
如果通过值复制的方式来传递复合数组,就需要为其创建一个复本,例如:
foo(a.slice());
相反如果要将基本类型的值传递到函数中并进行更改,就需要将值封装到一个复合对象中,然后进行传递。
function foo(o) { o.a = 11; } var obj = { a:2 } foo(obj); console.log(obj.a);
在看下基本类型对象传递时的问题:
function foo(x) { x = x + 1; console.log(x); } var a = 2; var b = new Number(a);//object(a)也一样 foo(b); console.log(b);//2
上面虽然传递的是对象的引用,但是也并未更改函数外部的值,原因是标量的基本类型值是不可以更改的(字符串和布尔也是如此),如果一个数字对象的标量基本类型值是2,那么该值就不能更改,
除非创建一个包含新值的数字对象。
x=x+1中,x中的标量基本类型值2从数组对象中拆封出来后,x就神不知鬼不觉的从引用变成了数字对象,他的值为3,然而函数外的b仍然指向原来的那个值为2的对象。