首页 > 代码库 > js按值传递还是按引用传递?
js按值传递还是按引用传递?
js和其他大部分语言一样,有基本类型和引用类型。因此访问变量就有按值和按引用两种方式,但是传参的时候却只能按值传递。基本类型作为参数时按值传递自然无可厚非,但引用类型作为参数也按值传递就让人有点困惑了。
看下面这个例子:
1 function setName(obj){ 2 3 obj.name = "Sim"; 4 5 } 6 7 var person = new Object(); 8 9 setName(person);10 11 alert(person.name); //"Sim"
以上代码创建了一个名为person的对象,并且将其作为参数传给了setName函数。我们在函数内部给传进来的对象添加了一个name属性并赋值,之后在函数外部访问person.name,会弹出"Sim"。一般我们都说,若是按值传递的话,形参在函数内的变化不会影响到实参的变化,但这个例子中,函数内部给形参加上的属性在实参中也有此属性。这会让人产生一种误解,感觉引用类型传参貌似是按照引用传递的啊!
下面再给出一个例子:
var obj1 = { value:‘111‘}; var obj2 = { value:‘222‘}; function changeStuff(obj){ obj.value = http://www.mamicode.com/‘333‘; obj = obj2; return obj.value;} var foo = changeStuff(obj1); console.log(foo);// ‘222‘ 参数obj指向了新的对象obj2console.log(obj1.value);//‘333‘
上面例子打印出了形参obj和实参obj1的value值我们可以清楚的看到,这两个value值并不一样,因此可以证明引用类型的参数并非是按照引用传递的。
至于为什么会出现这种情况,那就有必要来理解一下js中的数据存储与访问的机制了。
声明变量时的内存分配:
基本类型:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。
引用类型:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
复制变量时的不同:
基本类型:在将一个保存着原始值的变量复制给另一个变量时,会将基本类型的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
js按值传递还是按引用传递?