3.15 傳值呼叫、傳址呼叫

javascript/practice 資料夾下,建立 call_by_type.html 來練習。

將資料傳進參數時,要留意類型的部份,有分傳遞「值」、「址」兩種:

  • 傳值:傳遞變數的值。

  • 傳址:傳遞變數在記憶體中的「位址」。物件和陣列屬這類型。

範例 1:傳值呼叫(Call by Value)

在傳遞參數時,會複製其值至參數之中。

var a = 10;

function add_number(x){
  x = x + 10;
  alert(x); // 20
}

add_number(a);
alert(a); // 10
  • 第 8 行:將變數 a 的「值」傳給 add_number 函式,該函式用 x 來做承接。(下一節會提到變數的可視範圍)

範例 2:傳址呼叫(Call by Reference)

物件陣列皆為傳址呼叫的類型,即在傳遞參數時,傳的是該變數在記憶體中的位址。

示意:

以陣列為例:

var a = [1, 2];
function add_number(x){
  x.push(3);
}
add_number(a);  // 傳的是記憶體中的位址

console.log(a); // [1, 2, 3]

概念示意圖:

以物件為例:

var a = {first: "123", second: "456"};
function add_key(x){
  x.third = "789";
}
add_key(a);    // 傳的是記憶體中的位址

console.log(a); // {first: "123", second: "456", third: "789"}

範例 3:複製

延續範例 2,如果我們希望傳進去的陣列、物件,不要影響原來的,做法:

將陣列或物件進行複製,然後再傳遞即可。

以陣列為例:

var a = [1, 2];
function add_number(x){
  x.push(3);
  console.log(x); // [1, 2, 3]
}

add_number(a.slice());  // a.slice() 會回傳新的陣列
console.log(a); // [1, 2]

以物件為例:

var a = {first: "1", second: "2"};
function add_key(x){
  x.third = "3";
  console.log(x); // {first: "1", second: "2", third: "3"}
}

add_key(JSON.parse(JSON.stringify(a)));  // 物件字串化,再轉成物件
console.log(a); // {first: "1", second: "2"}

練習一:陣列

先執行以下原始碼,以下第4行,也影響到了 arr1:

var arr1 = ["a", "b", "c"];
var arr2 = arr1;

arr2[2] = "d";

console.log(arr1); // ["a", "b", "d"]
console.log(arr2); // ["a", "b", "d"]

請改成 arr1 陣列不影響。(也就是要先進行複製)

參考作法:

練習二:物件

先執行以下原始碼,以下第4行,發現也影響到了 obj1:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = obj1;

obj2.a = 50;

console.log(obj1); // {a: 50, b: 20, c: 30}
console.log(obj2); // {a: 50, b: 20, c: 30}

請改成 obj1 物件不影響。(也就是要先進行複製)

參考作法:

Last updated