結論:對於數字、字符串等是將它們的值傳遞給了函數參數,函數參數的改變不會影響函數外部的變量。
對於數組和對象等是將對象(數組)的變量的值傳遞給了函數參數,這個變量保存的指向對象(數組)的地址。當函數改變這個地址指向的對象(數組)的內容時,同時也改變了函數外部變量指向的對象(數組)的內容;當函數改變的是變量的地址時,實際就與函數外部的變量失去了聯系,變成了完全不同的對象了,不會對函數外部對象造成改變。
很多人認為 JS 中參數有兩種傳遞方式:數字、字符串等按值傳遞;數組、對象等按地址(引用)傳遞。其實都是一種值傳遞。下面的例子很好的說明了這一點。
var v1 = []
var v2 = {};
var v3 = {};
function foo(v1, v2, v3)
{
v1 = [1];
v2 = [2];
v3 = {a:3}
}
foo(v1, v2, v3);
alert (v1); // 空白
alert (v2); // [object Object]
alert (v3.a); // undefined
var v2 = {};
var v3 = {};
function foo(v1, v2, v3)
{
v1 = [1];
v2 = [2];
v3 = {a:3}
}
foo(v1, v2, v3);
alert (v1); // 空白
alert (v2); // [object Object]
alert (v3.a); // undefined
由此可見:v1、v2、v3 都沒有被改變,v1 仍然是零個元素的數組,v2、v3 仍然是空白的對象。
但是,數組、對象等按值傳遞,是指變量地址的值。
數組、對象等的按值傳遞與數字、字符串還是有所不同的。數字、字符串是把值直接復制進去了,而數組、對象是把變量地址復制進去的。
前面我們讓 v1、v2、v3 作為參數進入函數后,就有了地址副本,這些地址副本的指向和外面的 v1、v2、v3 的地址指向是相同的。但我們為 v1、v2、v3 賦了值,也就是說我們把地址副本的指向改變了,指向了新的數組和對象。這樣內部的 v1、v2、v3 和外部的 v1、v2、v3 就完全斷了。
如果我們不賦新值,而是直接操作它,那么,它操作到的,仍然是和外面的 v1、v2、v3 指向的同一塊數組或對象。
var v1 = []
var v2 = {};
var v3 = {a:0};
function foo(v1, v2, v3)
{
v1. push (1);
v2.a = 2;
v3.a = 3;
}
foo(v1, v2, v3);
alert (v1); // 1
alert (v2.a); // 2
alert (v3.a); // 3
var v2 = {};
var v3 = {a:0};
function foo(v1, v2, v3)
{
v1. push (1);
v2.a = 2;
v3.a = 3;
}
foo(v1, v2, v3);
alert (v1); // 1
alert (v2.a); // 2
alert (v3.a); // 3