# 3.15 傳值呼叫、傳址呼叫

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

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

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

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

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

```javascript
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)

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

示意：

![](https://3126711450-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LokjetmQhrMQC7IVioJ%2F-MTd7qfVYBd4rSJF1M10%2F-MTdCS0ZNien5qd0IKdE%2Fcall_by_type_and_value.png?alt=media\&token=d40c016e-767a-4632-8807-74a90626c966)

以陣列為例：

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

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

概念示意圖：

![](https://3126711450-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LokjetmQhrMQC7IVioJ%2Fuploads%2FSWiJQpXJ3z2HIMFoLmRG%2Fpass_by_ref.png?alt=media\&token=6c94c19b-b14c-46d1-958d-e3437a2151e0)

以物件為例：

```javascript
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，如果我們希望傳進去的陣列、物件，不要影響原來的，做法：

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

以陣列為例：

```javascript
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]
```

以物件為例：

```javascript
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：

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

arr2[2] = "d";

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

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

參考作法：

{% embed url="<https://codepen.io/carlos411/pen/gOrLppb>" %}

## 練習二：物件

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

```javascript
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 物件不影響。(也就是要先進行複製)

參考作法：

{% embed url="<https://codepen.io/carlos411/pen/KKzNpdm>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.webmix.cc/javascript/ji-chu/3.15-call-by-value-yu-call-by-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
