JS中函式引數值傳遞和引用傳遞

2022-02-08 02:58:32 字數 2744 閱讀 1834

也許大家對於函式的引數都不會太在意,簡單來說,把函式外部的值複製給函式內部的引數,就和把值從乙個變數複製到另乙個變數一樣。深入研究,你會發現其實沒那麼簡單,這個傳參是要分倆種情況(其實這是個錯誤的說法,ecmascript中所有函式的引數都是按值傳遞的——《高程3》原話,之所以這裡說倆種,是因為結合引用傳參更容易理解)—— 值傳參和引用傳參

。 值傳參針對基本型別,引用傳參針對引用型別,傳參可以理解為複製變數值。基本型別複製後倆個變數完全獨立,之後任何一方改變都不會影響另一方;引用型別複製的是引用(即指標),之後的任何一方改變都會對映到另一方。

不少人對引數都是按值傳遞的感到困惑,因為訪問變數有按值和按引用兩種方式

。下面就來看看有何不同:

這一段很重要我們可以把ecmascript函式的引數想象成區域性變數。在向引數傳遞基本型別的值時,被傳遞的值被複製給乙個區域性變數(即命名引數,或者用ecmascript的概念來說,就是arguments物件中的乙個元素)。在向引數傳遞引用型別時,會把這個值在記憶體中的位址(指標)複製給乙個區域性變數,因此這個區域性變數的變化會反映在函式的外部。

1

function

addten(num) 56

var count = 20;

7var result = addten(count); //

按值傳遞 num = count

8 alert(count); //

20, 沒變化

9 alert(result); //

30

很好理解,因為是按值傳遞的,傳遞完後倆個變數各不相干!

1

function

setname(obj) 45

var person = new

object();

6 setname(person); //

obj = person

7 alert(person.name); //

"nicholas" 看起來是按引用傳遞,但千萬不要以為是按引用傳遞~~~

var person = new object();時,可以用下圖表示變數和物件的關係:

當呼叫函式

setname(person);

時,下圖可以表示全域性變數person和區域性變數obj的關心:

以上**中建立乙個物件,並將其儲存在變數person中。然後,這個變數被傳遞到setname(obj)函式中之後就被複製給了obj。在這個函式內部,obj和person引用的是同乙個物件。換句話說,即使ecmascript說這個變數是按值傳遞的,但obj也會按引用來訪問同乙個物件。於是,在函式內部為obj新增name屬性後,函式外部的person也將有所反應;因為這時的person和obj指向同乙個堆記憶體位址。所以,很多人錯誤的認為:在區域性作用域中修改的物件會在全域性物件中反映出來,就說明引數是按引用傳遞的。

為了證明物件也是按值傳遞的,我們再來看看下面這個經過修改的例子:

1

function

setname(obj) 67

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的指向

綜上所述,還是覺得引數傳遞物件時是按引用傳遞的,歡迎指正!

JS中函式引數值傳遞和引用傳遞

自 1 按值傳遞 1 function addten num 5 6 var count 20 7 var result addten count 按值傳遞 num count 8 alert count 20,沒變化 9 alert result 30 很好理解,因為是按值傳遞的,傳遞完後倆個變數...

C 函式引數 值傳遞與引用傳遞

以前我們在c語言中函式引數傳遞過程中,如果我們想要讓當a函式作用域中的變數經過b函式處理之後的數值仍然在a函式中生效,這個時候函式引數的傳遞時需要引用方式去傳遞,方式如下 include 函式引數為指標,通過修改指標裡面的內容達到對main中b變數的修改 void func int a int ma...

結構體作為函式引數(值傳遞,引用傳遞,指標傳遞)

一 值傳遞 include include using namespace std struct student void outcome student s 引用傳遞不會進行記憶體重新分配,因此和指標傳參類似,效率很高 void outcome student s 引用傳參 outcome stu...