JavaScript 函數參數傳遞到底是值傳遞還是引用傳遞

在傳統的觀念裏,都認爲JavaScript函數傳遞的是引用傳遞(也稱之爲指針傳遞),也有人認爲是值傳遞和引用傳遞都具備。那麼JS的參數傳遞到底是怎麼回事呢?事實上以下的演示也完全可以用於Java

    首先來一個比較簡單的,基本類型的傳遞:

 

Java代碼  收藏代碼
  1. function add(num){   
  2.        num+=10;   
  3.        return num;   
  4.     }   
  5.     num=10;   
  6.     alert(add(num));   
  7.     aelrt(num);   
  8.     //輸出20,10 

 

  對於這裏的輸出20,10,按照JS的官方解釋就是在基本類型參數傳遞的時候,做了一件複製棧幀的拷貝動作,這樣外部聲明的變量num和函數參數的 num,擁有完全相同的值,但擁有完全不同的參數地址,兩者誰都不認識誰,在函數調用返回的時候彈出函數參數num棧幀。所以改變函數參數num,對原有 的外部變量沒有一點影響。

    再來看一個較複雜的,對象引用類型的傳遞:

 

Java代碼  收藏代碼

     

    1. function setName(obj){   
    2.     obj.name="ted";   
    3. }   
    4. var obj=new Object();   
    5. setName(obj);   
    6. alert(obj.name);   
    7. //輸出ted   

      以上代碼的運行的實質是:創建了一個object對象,將其引用賦給obj(在C裏面就直接是一個內存地址的賦值),然後在傳遞函數參數的時候,做了一件 與前一個方法相同的事情,複製了一個棧幀給函數參數的obj,兩者擁有相同的值(不妨將其理解爲object對象的地址),然後在setName做改變的 時候,事實上是改變了object對象自身的值(在JAVA裏稱之爲可變類),在改變完成之後同樣也要彈出函數參數obj對應的棧幀。

      所以對應的輸出是改變後object對象的值

     那麼可能有的朋友可能會問,這樣也可以理解爲一個引用傳遞(指針傳遞)呀?不,這裏嚴格的說,在和JAVA類似的語言中,已經沒有了指針,在JAVA裏將 上述過程稱之爲一個從符號引用到直接引用的解析過程。在C裏面,指針就是一個具有固定長度的類型(在大多數的C編譯器裏是2個字節),但在JAVA類似的 語言裏,引用也有自己的屬性和方法,只是你不能直接去訪問和控制它,所以它從某種意義上也是一種對象,這種機制也很大程度的避免了內存泄露,術語稱之爲內 存結構化訪問機制。

    爲了證明上述觀點,稍微改造下上述例子:

 

Js代碼  收藏代碼

     

    1. function setName(obj){   
    2.     obj.name="ted";   
    3.     obj=new Object();   
    4.     obj.name="marry";   
    5. }   
    6. var obj=new Object();   
    7. setName(obj);   
    8. alert(obj.name);   
    9. //輸出ted   

 

  這個例子與上一個例子的唯一不同是這裏將一個新的對象賦給了函數參數obj,這樣函數參數obj和原有的引用obj參數,有着完全不同的值和內存地址。

 

    值的一提的是,在Python中就沒有這樣的爭論,因爲Python裏面一切都是對象,只是對象可以按照存儲類型(容器類型還是標量模型) 、更新類型(是否可變)、訪問模型(直接訪問、序列訪問、映射訪問)來劃分,訪問模型是最多被討論的,也是最清晰的區分方式。所以毫無疑問,在 Python裏面,函數傳遞方式只有一種---引用對象傳遞

 

 


引自:http://bestchenwu.iteye.com/blog/1076557

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章