1. 程式人生 > 其它 >JavaScript函式引數傳值問題

JavaScript函式引數傳值問題

技術標籤:技術

JavaScript函式引數傳值問題

首先先上個結論,在JavaScript中函式只有值傳遞,沒有引用傳遞。

1.向引數傳遞基本資料型別

基本資料型別包括number、string這些。那麼當傳入這些基本型別時,是否可以通過形參來修改呢?
EXP:

var num = 123

function text(a){
   a = 1
   console.log(a)   //1
}

text(num)     //  1
console.log(num)     //123

通過上面例子可以看到不可以通過形參的數值修改修改來改變實參的值,上面的程式碼其實等價於下面程式碼

var
num = 123 function text() { var a = num // 函式內部的引數變數,賦值函式外部的值 a = 1 // 修改內部變數的值 console.log(a) //1 } text(num) // 1 console.log(num) // 123

通過上面的兩個程式碼片段我們可以知道,其實當向引數傳遞基本資料型別的數值時,函式內的引數只是複製了傳遞來的值在棧中開闢了一個新的空間和實參num是完全不同的兩個空間,所以修改了形參的值,只能改變自己並不會影響num本身。

2.向引數傳遞引用資料型別

引用資料型別包括陣列、物件這些。那麼是否可以通過修改引數的陣列來改變實參的值呢?我們來看看下面的例子。

EXP:


let obj = {
  name:'小紅'
}

function text(o)
{
  o.name = '小明'
}

text(obj)
console.log(obj.name)   //小明

通過上面的例子我們可以看到當傳遞引用資料型別時,可以通過修改引數的值來改變實參的值,為什麼呢?同理上面的程式碼等價與下面的程式碼:

let obj = {
  name:'小紅'
}

function text()
{
  var o = obj       //函式內部的引數變數,賦值函式外部的值,這個值其實是obj物件在堆記憶體中的地址值
  o.name = '小明'   //修改內部變數的值
} text(obj) console.log(obj.name) //小明

通過以上兩段程式碼,我們可以知道當吃傳遞是引用資料型別時,傳給引數的值其實是傳遞了物件在堆記憶體中的地址值,所以函式內部的引數o和obj都指向了同一個地址也就是同一個記憶體,所以修改了o的就等於修改了obj。

3.為什麼說函式只有值傳遞沒有引用傳遞

我們來看看下面這個例子:


function test(obj){
  obj.name = "小紅"
  obj = new Object()
  obj.name = "小明"
  console.log(obj.name)     //小明
}

var p = new Object()
test(p)
console.log(p.name)        //小紅 

通過上面的執行結果我可以知道,我們把p的地址值傳給了函式test的引數obj ,此時p和obj都指向了堆記憶體中的同一個地址,所以對obj的操作其實就是在這個地址上進行操作,所以相應的變化也會反應在p物件上。
然後,我們在對obj重新賦值後,這裡就切斷了obj和p間的地址聯絡,所以對obj的任何操作都不會反應到p物件上,因為兩者間已經沒有任何聯絡了。假設是引用傳遞的話那麼obj = new Object() 就會等價於 p = new Object(),那麼後面對obj的修改也會反應到p上 但是實際上並沒用,說明不是引用傳遞。

總結

1.JavaScript中所有函式都是按照值傳遞的。

2.基本資料型別傳遞的是實際值,引用資料型別傳遞的的地址值。

3.基本資料型別作為形參時,不能通過改變形參來改變實參的數值。

4.引用資料型別作為形參時,可以通過改變形參來改變實參所指向空間的值。