帶你深刻理解傳遞參數

ECMAScript中全部函數的參數都是按值傳遞的。也就是說,把函數外部的值複製給函數內部的參數,就和把值從一個變量複製到另外一個變量同樣。基本類型值的傳遞如同基本類型變量的複製同樣,而引用類型值的傳遞,則如同引用類型變量的複製同樣。有很多開發人員在這一點上可能會感到困惑,由於訪問變量有按值和按引用兩種方式,而參數只能按值傳遞。函數

在向參數傳遞基本類型的值時,被傳遞的值會被複制給一個局部變量(即命名參數,或者用ECMAScript的概念來講,就是arguments對象中的一個元素)。在向參數傳遞引用類型的值時,會把這個值在內存中的地址複製給一個局部變量,所以這個局部變量的變化會反映在函數的外部。請看下面這個例子:ui

function addTen(num) {
    num += 10;
    return num;
}
var count = 20;    
var result = addTen(count);
alert(count);    //20,沒有變化
alert(result);  //30
複製代碼

這裏的函數addTen()有一個參數num,而參數其實是函數的局部變量。在調用這個函數時,變量count做爲參數被傳遞給函數,這個變量的值是20。因而,數值20被複制給參數num以便在addTen()中使用。在函數內部,參數num的值被加上了10,但這一變化不會影響函數外部的count變量。參數num與變量count互不相識,它們僅僅是具備相同的值。假如num是按引用傳遞的話,那麼變量count的值也將變成30,從而反映函數內部的修改。固然,使用數值等基本類型值來講明按值傳遞參數比較簡單,但若是使用對象,那問題就不怎麼好理解了。再舉一個例子:spa

function setName(obj) {
obj.name = "Nicholas";    
 }
var person = new Object();
setName(person);
alert(person.name);    //"Nicholas" 
複製代碼

以上代碼中建立一個對象,並將其保存在了變量person中。而後,這個變量被傳遞到setName()函數中以後就被複制給了obj。在這個函數內部,obj和person引用的是同一個對象。換句話說,即便這個變量是按值傳遞的,obj也會按引用來訪問同一個對象。因而,當在函數內部爲obj添加name屬性後,函數外部的person也將有所反映;由於person指向的對象在堆內存中只有一個,並且是全局對象。有不少開發人員錯誤地認爲:在局部做用域中修改的對象會在全局做用域中反映出來,就說明參數是按引用傳遞的。code

相關文章
相關標籤/搜索