也許你們對於函數的參數都不會太在乎,簡單來講,把函數外部的值複製給函數內部的參數,就和把值從一個變量複製到另外一個變量同樣。深刻研究,你會發現其實沒那麼簡單,這個傳參是要分倆種狀況(其實這是個錯誤的說法,ECMAScript中全部函數的參數都是按值傳遞的——《高程3》原話,之因此這裏說倆種,是由於結合引用傳參更容易理解)—— 值傳參和引用傳參。 html
值傳參針對基本類型,引用傳參針對引用類型,傳參能夠理解爲複製變量值。基本類型複製後倆個變量徹底獨立,以後任何一方改變都不會影響另外一方;引用類型複製的是引用(即指針),以後的任何一方改變都會映射到另外一方。函數
很多人對參數都是按值傳遞的感到困惑,由於訪問變量有按值和按引用兩種方式。下面就來看看有何不一樣:spa
這一段很重要:咱們能夠把ECMAScript函數的參數想象成局部變量。在向參數傳遞基本類型的值時,被傳遞的值被複制給一個局部變量(即命名參數,或者用ECMAScript的概念來講,就是arguments對象中的一個元素)。在向參數傳遞引用類型時,會把這個值在內存中的地址(指針)複製給一個局部變量,所以這個局部變量的變化會反映在函數的外部。指針
1 function addTen(num) { 2 num += 10; 3 return num; 4 } 5 6 var count = 20; 7 var result = addTen(count); //按值傳遞 num = count 8 alert(count); // 20, 沒變化 9 alert(result); // 30
很好理解,由於是按值傳遞的,傳遞完後倆個變量各不相干!code
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 } 4 5 var person = new Object(); 6 setName(person); // obj = person 7 alert(person.name); // "Nicholas" 看起來是按引用傳遞,但千萬不要覺得是按引用傳遞~~~
當 var person = new Object(); 時,能夠用下圖表示變量和對象的關係:htm
當調用函數 setName(person); 時,下圖能夠表示全局變量person和局部變量obj的關心:對象
以上代碼中建立一個對象,並將其保存在變量person中。而後,這個變量被傳遞到setName(obj)函數中以後就被複制給了obj。在這個函數內部,obj和person引用的是同一個對象。換句話說,即便ECMAScript說這個變量是按值傳遞的,但obj也會按引用來訪問同一個對象。因而,在函數內部爲obj添加name屬性後,函數外部的person也將有所反應;由於這時的person和obj指向同一個堆內存地址。因此,不少人錯誤的認爲:在局部做用域中修改的對象會在全局對象中反映出來,就說明參數是按引用傳遞的。blog
爲了證實對象也是按值傳遞的,咱們再來看看下面這個通過修改的例子:ip
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 obj = new Object(); //改變obj的指向,此時obj指向一個新的內存地址,再也不和person指向同一個 4 obj.name = "Greg"; 5 } 6 7 var person = new Object(); 8 setName(person); //你看看下面,相信我也是按值傳遞的了吧 9 alert(person.name); //"Nicholas"
當建立obj對象 obj = new Object(); 時,來看看這時person和obj的關係圖:內存
這個例子與前一個惟一的區別,就是setName()函數中添加了兩行代碼: obj = new Object(); 用來改變obj的指向; obj.name = "Greg"; 用來給新建立的obj添加屬性。若是是按引用傳遞的,那麼person就會自動被修改成指向新建立的obj的內存地址,則person的name屬性值被修改成"Greg"(這句話以前說的有誤,引用傳遞的是指針的值,obj=new Object()改寫了本身的指向,並不會影響到person的指向,這種方式就是按引用傳遞。即便不把對象賦值給函數的參數,obj改寫指向對person也沒影響,見下面代碼)。可是,當訪問person.name時,顯示的結果爲"Nicholas"。這說明即便在函數內部修改了參數的值,但原始的引用仍然保持未變。實際上,當在函數內部重寫obj時,這個變量引用的就是一個局部對象了。而這個局部對象會在函數執行完畢後被當即銷燬!
推翻以上都是按值傳遞的結論:
var person=new Object(); var obj = person; // 賦值 obj.name="ABC"; obj=new Object(); obj.name="BCD"; console.log(person.name);// ABC 並無影響person的指向
綜上所述,仍是以爲參數傳遞對象時是按引用傳遞的,歡迎指正!