標籤:alt var 調用 但我 獨立 相同 值傳遞 技術分享 拷貝
資料類型基礎資料型別 (Elementary Data Type)
number、string、boolean、null、undefined 基礎資料型別 (Elementary Data Type)的值儲存在棧中;
引用資料類型
array、object、function 等對象,參考型別的資料儲存分為兩部分:
其中棧中是儲存地址的引用,堆中儲存真正的值 如
什麼是按值傳遞?什麼是按引用傳遞?
按值傳遞(call by value):函數的形參是被調用時所傳實參的副本,修改形參的值並不會影響實參。
按引用傳遞(call by reference)時,函數的形參接收實參的隱式引用,而不再是副本。這意味著函數形參的值如果被修改,實參也會被修改,同時兩者指向相同的記憶體位址。
Js傳遞方式
參數是基礎資料型別 (Elementary Data Type):
1 var a = 10;2 function add(a) {3 a = 20;4 console.log(a);//205 }6 add(a);7 console.log(a);//10
變數a在add 內部改變了值,並沒有影響到外部的a變數;
參數是參考型別:
1 //參考型別2 var person = {name: ‘joel‘, age: 11}3 function foo(o) {4 o.name = ‘alen‘;//改變對象的值5 o = {name: ‘elire‘}//改變對象的地址6 console.log(o.name); //elire7 }8 foo(person);9 console.log(person.name);//alen
如果是按照引用傳遞,傳進去的o對象跟外部的person對象指向的記憶體應該是同一個,但是foo()內部o.name 是elire,外部的person.name 是alen,所以儘管是參考型別資料傳遞的時候也不是按引用傳遞;
繼續看下面demo:
1 var v1 = [] 2 var v2 = {}; 3 var v3 = {}; 4 function demo1(v1, v2, v3) 5 { 6 v1 = [1]; 7 v2 = [2]; 8 v3 = {a:3} 9 }10 demo1(v1, v2, v3);11 console.log(v1); // 空白12 console.log(v2); // [object Object]13 console.log(v3.a); // undefined
由此可見:v1、v2、v3 都沒有被改變,v1 仍然是零個元素的數組,v2、v3 仍然是空白的對象。即參考型別資料也是按照值傳遞的,先是拷貝了棧中的地址,然後在demo1()內部改變了地址的指向。
但是參考型別按值傳遞與基本類型資料按值傳遞還是有區別的。
基礎資料型別 (Elementary Data Type),如數字、字串是把值直接複製進去了,而參考型別 如數組、對象是把變數地址複製進去。
前面我們讓 v1、v2、v3 作為參數進入函數後,就有了地址副本,這些地址副本的指向和外面的 v1、v2、v3 的地址指向是相同的。但我們為 v1、v2、v3 賦了值,也就是說我們把地址副本的指向改變了,指向了新的數組和對象。這樣內部的 v1、v2、v3 和外部的 v1、v2、v3 就完全斷了。
如果我們不賦新值,而是直接操作它,那麼傳進去的仍然是和外面的 v1、v2、v3 指向的同一塊數組或對象,因為我們沒有改變他們的指向。
如:
1 var v1 = [] 2 var v2 = {}; 3 var v3 = {a:0}; 4 function demo2(v1, v2, v3) 5 { 6 v1.push (1); 7 v2.a = 2; 8 v3.a = 3; 9 }10 11 demo2(v1, v2, v3);12 console.log(v1); // 113 console.log(v2.a); // 214 console.log(v3.a); // 3
總結
基礎資料型別 (Elementary Data Type),如數字、字串是把值複製進去,而參考型別 如數組、對象是把變數地址複製進去,
如果沒有改變傳進去的地址指向,那麼它們都是指向同一個記憶體位址;
如果改變了地址指向那麼它們跟外部的對象是兩個獨立的對象,互不干擾;
js傳參是按值傳遞還是按引用傳遞?