瞭解參數的傳遞以前咱們來複習下變量的類型,JavaScript中的變量有5個基本數據類型(Undefined, Null, Boolean, Number, String)和引用數據類型(Object,Function,Array等)。函數
// 聲明一個String類型的變量spa
var str = "string";
// 聲明一個引用類型的變量,並添加屬性code
var person = new Object(); person.name = "Jeremy";
兩者的區別主要在於對變量內容保存的方式,基本類型的變量中存儲的就是簡單的數據段,而引用類型變量存儲的是指向對象的引用,好比:對象
// 基本類型的變量複製,能夠看出基本類型變量存儲的就是變量的值blog
var num1 = 5; var num2 = num1; console.log(num2); //5
num1的5與num2的5是徹底獨立的,這兩個變量能夠參與任何操做而不會相互影響。下圖可以形象的展現複製過程。ip
// 引用類型的變量複製,能夠看出引用變量中存儲的是指向對象的引用rem
// Object對象存儲於堆中,而obj1和obj2分別存儲了指向此Object對象的引用get
var obj1 = new Object(); obj1.name = "Jeremy"; var obj2 = obj1; obj2.name = "James"; console.log(obj1.name); //James
首先變量obj1保存了一個對象的新實例,又給obj1添加一個新屬性name,後obj1對象被複制給了obj2,obj2也有了name這個屬性,而且訪問的地址是跟obj1的name屬性是一個地址,因此當修改了obj2的那麼屬性的話,那obj1的name屬性也會改變。下圖展現了保存在變量對象中的變量和保存在堆中的對象之間的這種關係。string
在JavaScript中不管是基本類型仍是引用類型,函數參數都是按值傳遞的,先來看基本類型:it
function test(num) { num += 10; return num; } var num = 10; var res = test(num); console.log(num); //10 外部變量並未受到影響 console.log(res); //20
接下來看引用類型:
function setName(obj) { obj.name = "James"; } var person = new Object(); person.name = "Jeremy"; setName(person);
console.log(person.name);//James 影響到了外部引用變量
乍一看,這不就是按引用傳遞嗎?怎麼會是按值傳遞呢?之因此是按值傳遞是由於當調用setName(person)的時候,其實是把person所指向的對象的引用進行了複製,而後傳遞給了setName函數,這樣在函數setName內部對此引用進行操做時候是會影響到此引用所指向的對象,即外部person所指向的對象。
總的來講,基本類型的參數傳遞複製的是具體的值,而引用類型的參數傳遞複製的是這個引用變量存儲的對對象的引用。
爲了進一步證實引用類型的參數傳遞是按值傳遞而不是按引用傳遞的,請看:
function setName(obj) { obj.name = "James"; obj = new Object(); obj.name = "Leon" } var person = new Object(); person.name = "Jeremy"; setName(person); console.log(person.name);//James
以上代碼輸出的是James,若是是按引用傳遞,那麼以上代碼輸出的是Leon。實際上,當執行obj.name = "James"的時候,引用所指向的對象的值已經發生了改變,當在對obj進行覆蓋的時候,obj的值是一個指向局部對象的引用,而這個引用沒法對外部的對象產生影響,而且此對象會在函數執行結束以後銷燬。