搞懂Javascript傳值、傳址觀念
前言
剛開始接觸傳值(pass by value)和傳址(pass by reference)時,常常會搞混,如果觀念似懂非懂的話在開發專案的時候可能會不自覺踩到雷,這一篇就把這個觀念好好記錄下來。
傳值(pass by value)
string、number、boolean、null、undefined都是基本型別,所以會根據pass by value的方式來運作,另外function 也是以此方式運作
舉例:
1 | let a = 666; |
第2行:把a值指派給b變數,所以b值為666
第6行:把a值設為777
第8行:b值還是本來的值,也就是666
傳址(pass by reference)
物件裡面的屬性會根據pass by reference來運作
1 | let son = { |
第4行:把son值指派給father變數,所以father值為{age: 18}
第7行:將son的age屬性改為40
第9行:father的age屬性值也會變成40
第11行:son 完全等於father,因為是共用一份記憶體
陣列也會依據pass by reference來運作
1 | let arr1 = [1, 2, 3]; |
第4行:針對arr1再多push4的值
第6行:也改動到了arr2的值
所以常常在實戰中,習慣複製一份出來,再做相關操作
可以在第2行改為let arr2 = arr1.slice(0);
或是用ES6擴展符let arr2 = [ ...arr1 ]
方式來賦值 (前提裡面的元素不要是物件或陣列)
如此一來arr2就不會受到任何影響了
其他種情況
如果我們現在是把整個物件取代掉,會發生什麼事呢?
1 | let son = { |
第7行:son賦予整個物件{ age: 5 }
第9行:father的age仍然是18,因為son是重新賦值,會產生一個新的實體參考,所以不會影響到father的age值
這種情況有人稱它為pass by sharing,也有人會認為說這個其實就是pass by value,我們就不在名詞上面爭議,理解一下概念即可。
陣列也會有這樣的情況,如果是賦予一個全新陣列,也會跟本來的獨立,這邊就不額外舉例了。
小結
- 了解pass by value和pass by reference的差異
- 僅修改物件或陣列裡面的值以及賦予整個物件或陣列,結果會不同(因記憶體指向的差異)