JS基礎 引用型別的引數傳遞

2021-10-09 10:42:46 字數 2673 閱讀 2637

ecmascript中所有函式的引數都是按值傳遞的。可以把ecmascript函式的引數想象成區域性變數。

ecmascript中所有函式的引數都是按值傳遞的。也就是說,函式的傳參,就和基本型別變數的複製一樣,而引用型別值的傳遞,則如同引用型別變數的複製一樣。這裡可能會使很多人感到困惑,因為訪問變數有按值和按引用兩種方式,而引數只能按值傳遞。

請看下面這個例子:

function

add(

num)

var count =20;

var result =

add(count)

;console.

log(count)

;//20

console.

log(num)

;//30

在呼叫add()函式時,變數count作為引數被傳遞給函式。於是,數值20被複製給引數num。在函式內部,引數num的值被加上了10,但這一變化不會影響函式外部的count變數。

引數num與變數count互不相識,它們僅僅是具有相同的值。假如num是按引用傳遞的話,那麼變數count的值也將變成30,從而反映函式內部的修改。

當然,使用數值等基本型別值來說明按值傳遞引數比較簡單,但如果使用物件,那問題就不怎麼好理解了。再舉乙個例子:

function

setname

(obj

)var person =

newobject()

;setname

(person)

;console.

log(person.name)

;//"tom"

以上**中建立乙個物件,並將其儲存在了變數person中。然後,這個變數被傳遞到setname()函式中之後就被複製給了obj。在這個函式內部,obj和person引用的是同乙個物件

換句話說,即使這個變數是按值傳遞的,obj也會按引用來訪問同乙個物件。於是,當在函式內部為obj新增name屬性後,函式外部的person也將有所反映;因為person指向的物件在堆記憶體中只有乙個,而且是全域性物件。

有很多人錯誤地認為:在區域性作用域中修改的物件會在全域性作用域中反映出來,就說明引數是按引用傳遞的。為了證明物件是按值傳遞的,我們再看一看下面這個經過修改的例子:

function

setname

(obj

)var person =

newobject()

;setname

(person)

;console.

log(person.name)

;//"tom"

這個例子與前乙個例子的唯一區別,就是在setname()函式中新增了兩行**:一行**為obj重新定義了乙個物件,另一行**為該物件定義了乙個帶有不同值的name屬性。

在把person傳遞給setname()後,其name屬性被設定為"tom"。然後,又將乙個新物件賦給變數obj,同時將其name屬性設定為"pack"。如果person是按引用傳遞的,那麼person就會自動被修改為指向其name屬性值為"pack"的新物件。但是,當接下來再訪問person.name時,顯示的值仍然是"tom"。這說明即使在函式內部修改了引數的值,但原始的引用仍然保持未變。

實際上,當在函式內部重寫obj時,這個變數引用的就是乙個區域性物件了。而這個區域性物件會在函式執行完畢後立即被銷毀。

再來看另乙個例子,我們期望是將兩個物件進行相互交換:

function

swap

(objone, objtwo

)var one =

newobject()

;var two =

newobject()

;one.name =

"tom"

;two.name =

"pack"

;swap

(one, two)

;console.

log(one.name)

;//「tom」

console.

log(two.nama)

;//"pack"

以上**建立了兩個物件,並將其儲存在了變數one和two中。然後,這兩個變數被傳遞到swap()函式中之後就被分別複製給了objone和objtwo。在這個函式內部,objone和one引用的是同乙個物件,objtwo和two引用的是同乙個物件。在swap()函式內部建立了乙個新的物件obj用來交換objone和objtwo這兩個物件。但是,接下來訪問one.name和two.name時,仍然顯示的是原來的變數。

那是因為,在swap()函式傳遞引數時,使用的是值傳遞。而引用型別變數的值實際上是乙個指標,這個指標指向儲存在堆中的乙個物件。在swap()函式內部進行交換時,只是將函式的量區域性變數objone和objtwo的值進行了交換,該操作並不影響函式外部one和two兩個變數的值。因此,one和two這兩個變數的值仍然保持不變,即這兩個變數內部的指標仍然指向原來堆記憶體。

通過下面兩張,我們可以清楚的看出函式執行前後,各個物件變數的指標指向。

可以看出,在函式執行前後,外部變數所儲存的指標始終沒有發生指向的改變,這也恰恰驗證了我們最開始的結論:ecmascript中所有函式的引數都是按值傳遞的。

js 函式 引數傳遞 引用型別與基本型別

1.js函式不介意傳遞進來多少個引數,也不在乎傳遞進來引數是什麼型別。2.arguments物件 類陣列 arguments物件的長度是由傳入的引數個數決定的,不是由定義函式時的引數 命名引數 個數決定的。沒有傳遞值的命名引數自動被賦予undefined值。用var操作符定義的變數將成為作用域中的區...

值傳遞與引用傳遞 引數型別

根據儲存方式不同,我們將資料型別分為值型別和引用型別。值型別 基本資料型別 int float double boolean long 列舉 結構。儲存在棧當中的,提取資料快,但是分配空間多,耗資源,建議資料量少的情況下使用。引用型別 object型別 類 陣列 介面 值傳遞 1 直接傳遞值型別 結...

js 基本型別和引用型別 變數複製 引數傳遞

ecmascript 變數可能包含兩種不同資料型別的值 基本型別值和引用型別值 基本型別值指的是 簡單的資料段 undefined null boolean number 和 string 這 5 種基本資料型別是按值訪問 的,因為可以操作儲存在變數中的實際的值。而引用型別值指那些可能由多個值構成的...