在JavaScript紅寶書中說到,「ECMAScript中全部函數的參數都是按值傳遞的」。理解這個概念先要從JS的堆內存和棧內存提及:棧內存爲自動分配的內存空間,它由系統自動釋放;堆內存則是動態分配的內存,大小不定也不會自動釋放。(很初級的理解,有錯誤還望指正)
函數
JS中的5種基本數據類型Undefined、Null、Boolean、Number 和 String,它們是直接按值存放在棧內存中,能夠直接訪問。引用類型的值是保存在堆內存中的對象。與其餘語言不一樣,JavaScript不容許直接訪問堆內存中的位置, 也就是說不能直接操做堆內存中的對象。 在操做對象時, 其實是在操做對象的引用(也可理解爲指針)而不是實際的對象。」 這個堆內存中對象的引用(指針)存儲在棧內存中。你只能操做棧內存中的數據。即基礎類型數據和堆內存中對象的指針兩大類學習
對於基本數據類型的複製就至關於你和小明買了一輛同樣的單車,你對本身單車的操做不會影響到小明的單車。
而對於引用類型的複製,至關於你和小明共用一個客廳,你對這個客廳作的操做是會影響到小明的客廳(即大家共用的客廳)測試
以下圖:
spa
//測試代碼: //基本類型: var a = 10; var b = a; b = 12; alert(a);//10 alert(b);//12 //引用類型: var a = new Object(); a.name = "Tony"; alert(a.name);//"Tony" var b = a; b.name = "Tom" alert(a.name);//"Tom"
繼續說參數的傳遞,不管參數是什麼類型,都是按值傳遞的,普通類型傳遞的是自己的值,引用類型傳遞的是本身在棧內存中的「指針」值。指針
function setName(obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); // "Nicholas"
實際過程以下圖
...]code
//而有一個容易引發誤導的點在於下面這個變化 function setName(obj) { obj.name = "Nicholas"; obj = new Object(); //改變obj的指向,此時obj指向一個新的內存地址,再也不和person指向同一個 obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); //"Nicholas" //這裏只要理解,你不能直接操做堆內存中的對象,你只能經過棧內存中的指針進行操做。
這個函數的過程以下圖:
對象