需要明白,js基本类型存放在栈,对象存放在堆。
结论:基本类型变量作为参数,不会改变变量值。对象变量作为参数,不修改属性(访问原始对象的操作),也不会改变变量值
起因,是群里一个问题:
var a = [1,2,3];
function f(a){
a = [4,2,3];
}
f(a);
a // [1, 2, 3] //数组内部的值没有发生改变 var a = [1,2,3];
function f(a){
a[0]=4;
}
f(a);
a // [4,2,3]
最后数组a的值发生了改变
参阅了两篇文章。
参数为基本类型时,
var x=1,y="dss";
function f(a,b){
a=2;
b="ww";
}
f(x,y);
x + " and " + y ;// "1 and dss"
不会变化,因为传入参数的是一个值,”按照JS的官方解释就是在基本类型参数传递的时候,做了一件复制栈帧的拷贝动作,这样外部声明的变量num和函数参数的num,拥有完全
相同的值,但拥有完全不同的参数地址,他们在内存中处于不同的位置“,因此改变a,b两个参数的值不会对原值起作用。那像开头的例子那样给基本类型变量改变属性呢?
var x=1,y="dss";
function f(a,b){
a.u=2;
b.s="ww";
}
f(x,y);
x.u+" and "+y.s;//"undefined and undefined"
不会有任何变化,这里还牵扯到包装对象的知识点。但是不慌,记住,基本变量作为参数传值时,不会改变其原始值。(不作为参数当然可以了,访问全局变量赋值太常见了。)
那么参数为对象时,就像上面那样。原因何在呢。
参数传递可以视为引用传递,在函数里,参数a复制了全局变量a,代表[1,2,3]在内存中的地址(姑且这样理解),给参数a赋值,当然对原始对象不会有什么影响。而且对全局变量a
也没有影响,应该说,参数始终只是复制一个栈堆。
下面有很好的两个例子:
function setName(obj){
obj.name="ted";
}
var obj=new Object();
setName(obj);
alert(obj.name);
//输出ted
function setName(obj){
obj.name="ted";
obj=new Object();
obj.name="marry";
}
var obj=new Object();
setName(obj);
alert(obj.name);
//输出ted
第一个里面,通过参数的引用,将原始对象的name属性修改了。而在第二个里面,因为new Object,那个obj已经是一个新的对象了。与name为ted的原始对象无关。所以没有改变。
感觉说的不清楚。