ECMAScript中所有函数的参数都是按值传递的。
理解这句话,只要弄清楚一点:保存对象的变量,它里面装的值是这个对象在堆内存中的地址。
1.数据类型
javascript的数据类型可分为两类:
-
原始数据类型:比如Undefined,Null,Boolean,Number,String。它是存储在栈(stack)中的简单数据段,它的值直接存储在变量访问的位置,因此可以直接得到变量的值。
-
引用类型:也就是对象,比如Object,Array,Function,Date。它是存储在堆(heap)中的对象,存储的值是一个指针,指向对象存储的内存地址。
javascript不允许直接访问保存在堆内存中的对象,访问时先得到这个对象在堆内存中的地址,然后按照这个地址获得对象的值,即为按引用访问。
2.复制变量
-
原始值:将一个保存原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后两个变量完全独立,他们只是拥有相同的value。
-
引用值:将一个保存着对象内存地址的变量赋值给另一个对象时,会把这个内存地址赋值给新对象,此后他们指向堆内存中的同一个对象,任何一个改变都会影响另一个。
3.参数传递
可以将参数传递的过程,理解为把实参复制给形参的过程。
- 原始值:只是把变量里的值传递给参数,之后参数和这个变量相互独立
- 引用值:传递的值是对象的内存地址,函数内部对参数修改会影响外部的变量
例如
var value = 1; //原始值
function foo(v) {
v = 2;
console.log(v); //2
}
foo(value);
console.log(value) // 1
注意: 引用值的变量把它的值赋值给了参数,让参数也指向原对象。
但是如果在函数内部,给参数赋值另一个对象,这个参数会更改它的值指向新对象的地址,此时原对象仍然指向原对象的地址,这时候他们是相互独立的。
如果参数只是改变对象内部的属性的话,他们共同指向的对象也会被修改。
例如:
var obj1 = {
value:'111'
};
var obj2 = {
value:'222'
};
function changeStuff(obj){
obj.value = '333'; //obj指向obj1,改变内部属性
obj = obj2; //赋值新对象,obj指向obj2
return obj.value;
}
var foo = changeStuff(obj1);
console.log(foo);// '222'
console.log(obj1.value);//'333'