標籤:
先把收穫晾一下:
1.javascrip變數包含兩種類型的值,一種為參考型別的值,一種是基本類型的值。參考型別包括:Array,Object,Function(可以這麼理解,非基本類型的都是參考型別);5種基本類型包括:undefined,null,string,boolean,number
2.函數的參數的傳遞的機制是複製變數值。
書上說:”把函數外部的值複製給函數內部的參數,就和把值從一個變數複製給另一個變數一樣。基本類型的傳遞如同基本類型變數的複製一樣,而參考型別的則如同參考型別變數的複製一樣。“
”當一個變數複製參考型別的值時,同樣也會將儲存在變數對象中的值複製一份放到為新變數分配的空間中。不同的是這個值的副本實際上是一個指標,而這個指標指向儲存在堆中的一個對象。複製操作結束後,兩個變數實際上將引用同一個對象。因此改變其中一個變數,就會影響到另一個變數。“
【注意:複製參考型別的值,才是傳址】
3.參數實際上是函數的局部變數。
----------------------------------------------------------------------------
基本概念的解釋:
傳值:把A的數值傳到B,改變B,A不會跟著變,B存的是跟A一樣的值;
傳址:把A的地址傳到B,改變B,A同時跟著變,B存的只是A的地址(類似電腦的捷徑)。
一個具有實值型別(value type)的資料存放在棧內的一個變數中。即是在棧中分配記憶體空間,直接儲存所包含的值,其值就代表資料本身。實值型別的資料具有較快的存取速度。
一個具有參考型別(reference type)的資料並不駐留在棧中,而是儲存於堆中。即是在堆中分配記憶體空間,不直接儲存所包含的值,而是指向所要儲存的值,其值代表的是所指向的地址。當訪問一個具有參考型別的資料時,需要到棧中檢查變數的內容,該變數引用堆中的一個實際資料。參考型別的資料比實值型別的資料具有更大的儲存規模和較低的訪問速度。
----------------------------------------------------------------------------
下面是三個問題。
【問題1】:為什麼change(a)函數執行完之後,外面的a沒有受幹擾呢?
<script>var a = [1, 2, 3];function change(a) { console.log(a);//[1,2,3] a = 2; //傳值 console.log(a);//2}change(a);console.log(a); //[1,2,3] </script>
問題1解答:因為change(a)的執行過程是這樣的,首先將對象a(數組)傳入到change以後,被複製給change的參數a。而後a=2是一個指派陳述式,變成傳值。此時a=2是實值型別,並不涉及引用地址的問題。所以並沒有影響外部的a。
【問題2】:為什麼change(a)函數執行完之後,外面的a受到幹擾呢?
<script> var a = [1, 2, 3]; function change() { a = 2;//傳值 } change(); console.log(a); //2 </script>
問題2解答:當執行change()的時候,函數在自己的執行環境中找尋範圍鏈,使用中的物件(activation object)並不包含變數a,於是沿著範圍鏈向上找,找到全域執行環境,發現變數a,於是此時函數內部的a和外部a在記憶體上是同一個地址,自然函數內部a變了,外部也會跟著變。
解析:問題2和問題1的區別在於,問題2並沒有引入參數,所以不涉及複製變數的事情。
【問題3】:為什麼change(a)函數執行完之後,外面的a受到幹擾呢?
<script> var a = [1, 2, 3]; function change(b) { b[0] = 2; } change(a); console.log(a); //[2,2,3]</script>
問題3解答:這個和問題1非常類似,唯獨不一樣的就是a=2,換成了b[0]=2,我一開始也很疑惑,不說複製嗎?參數b應該是個複製值,怎麼會影響到外面的a呢?
的確,change函數執行時,參數b是a的複製值。因為a是參考型別,所以在函數內部是b和a按引用來訪問的是一個地址的對象。b[0]=2的出現,並不影響在函數內部b和a引用的是同一個對象。
【問題4】:為什麼change(a)函數執行完之後,外面的a沒有受到幹擾呢?
var a = [1, 2, 3]; function change(b) { console.log(b);//[1,2,3] b=2; b[0] = 2; } change(a); console.log(a); //[1,2,3]
問題4解答:change(b)執行過程是這樣的,a對象傳入change函數,將值和地址複製給b。b=2這句,此時b變成實值型別了,並不涉及地址引用的問題,之後b[0]=2這句實際上毫無意義,因為此時b已經不是數組了,自然不具有b[0]這樣的索引方式。所以b與a的地址參考關聯性其實在b=2之後就消失了。此時外界的a仍然是[1,2,3];
參考書籍:
《Javascript進階程式設計(第3版)》
js- 引用和複製(傳值和傳址)http://blog.csdn.net/zzzaquarius/article/details/4902235
javascript的變數,傳值和傳址,參數之間關係