---
# System prepended metadata

title: 函式

---

20211028
# 函式
是物件的一種，通常一個函式會包含三個部分：

- 函式的名稱 (也可沒有名稱)
- 在括號 ( ) 中的部分，稱為「參數 (arguments) 」，參數與參數之間會用逗號 , 隔開
- 在大括號 { } 內的部分，內含需要重複執行的內容，是函式功能的主要區塊。

### 參數 (Parameter) 
可以透過「函式名稱」加上「小括號」的方式呼叫。 而小括號內的資料，就是「參數」。
**參數：在函式定義中所列出的變數**
```javascript=
function plus(numA, numB) {
  let total =numA + numB;
  return total;
};

plus(1, 2);      // 3
plus(3);      // NaN
```
上方例子中，括號內的 numA、numB 就是 參數
:::info
function 沒有參數也是能執行的
而在 JavaScript 裡，函式中的參數，預設值都是 **undefined**
也可以在一開始就給 **參數指定預設值**
:::

### 引數 (Arguments)
**呼叫函式時，傳給該函式的參數的值**
```javascript=
function show(a,b,c){
    console.log(a,b,c);
    console.log(arguments);
    console.log(arguments[0]);
    console.log(arguments.length);
    console.log(typeof arguments);
}
show(1,2,3);
```
![](https://i.imgur.com/qib15zq.png)

:::info
- arguments 儲存了所有傳遞參數的值。且還可以用length屬性
- 但**它並不是一個陣列**，是一個叫做**類陣列**的東西，也就是說無法使用 JS 提供給 array 的函式庫。
:::

```javascript=
function eatFood(fruit, vegetable) {

 console.log(arguments)
 console.log(arguments.length);
};

eatFood('apple', 'cabbage')
```

```javascript=
//用在迴圈
const sum = function () {
  let num = 0;
  for (var i = 0; i < arguments.length; i++) {
    num += arguments[i];
  }
  return num;
};
sum(3, 4, 5); // 12
```
```javascript=
// 抓出最大值
Max(1,5,100,20); // 100

function Max() {
  var max = 0;
  var num = arguments; // 把引數陣列丟進num
  // num.length → 4
  // num[0] → 1 ; num[1] → 5; num[2] → 100...

  for (var i=0; i<num.length; i++) {
    if (max < num[i]) max = num[i]; // 當前元素大於max時，max更新
  }
  return max;
}
```

### 以「物件」作為參數
將多個參數用一個「物件」包裝起來。

```javascript=
function card(Name, phone, email, address) {
}

card();
//'Woody', '0912345678', 'aa@gmail.com','Taipei'
```
順序不能錯，參數不能漏，少了一個，位置就會錯

#### 改用「物件」的方式來取代這一堆參數

```javascript=

let card = {
  Name: 'Woody',
  phone: '0912345678',
  email: '0987654321',
  address: 'aa@gmail.com',
  address: 'Taipei'
};


addPerson(card);
```

### 參數的預設檢查
上面提到參數可以多，但少了就會"undefined"

避免出現NaN，可以改寫：
```javascript=
function plus(numA, numB) {
  let total =(numA||0) + (numB||0);
  return total;
};

plus(2,3); // 5
plus(99); //99
```

# 閉包（Closure）
- 閉包就是 Function 內的 Function（上面就是兩層function)
- 閉包內層的變數記憶體不會被釋放，**可以被內層函式，不會被外面直接讀取**

```javascript=
function foo() {
  var a = 2;

  function bar() {
    console.log(a);
  }

  return bar;
}

var baz = foo();

baz(); // 2
```
```javascript=
function wait(message) {
  setTimeout(function() {
    console.log(message);
  }, 1000);
}

wait('hi, Closure!');
```

迴圈與閉包
```javascript=
for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}
//5 5 5 5 5 
//上面這段 code 執行的結果是
//單純的印出 i，但印的不是執行 setTimeout 時的 i，是執行 console.log(i) 時的 i；
//所以當迴圈跑完時， i 的值會停在 5（迴圈終止），最後 才執行 console.log(i)  就會一直是 5。


// 建立立即函式
for (var i = 0; i < 5; i++) {
  (function(i) {
    setTimeout(function() {
      console.log(i);
    }, i * 1000);
  })(i);
}


//使用let
for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}
```

setTimeout 語法 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout)
```
var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);

arg1, ..., argN 任選
附加參數，它們會作為參數傳遞function 
```
```javascript=
for (var i = 0; i < 5; i++) {
  setTimeout(function(i) {
    console.log(i);
  }, i * 1000,i);
}
//
```

bind寫法我還不懂，待補充


## 參考資料
1. [設計看JS - Parameter & Argument](https://ithelp.ithome.com.tw/articles/10240992)
2. [學JS的心路歷程 Day7-函式（二） arguments](https://ithelp.ithome.com.tw/articles/10204008)
3. [Javascript大全 - 06 函式(二) 參數、引數、閉包](https://yakimhsu.com/javascript/JS_Daquan-06_2.html)
4. [[JavaScript] 理解 JS中的arguments 與 parameters](https://dean34520.medium.com/%E7%90%86%E8%A7%A3-javascript%E4%B8%AD%E7%9A%84arguments-%E8%88%87-parameters-5028336976f6)
5. [[Day19] 參數（上）](https://ithelp.ithome.com.tw/articles/10277444)
6. [你懂 JavaScript 嗎？#15 閉包（Closure）](https://cythilya.github.io/2018/10/22/closure/)
7. [Tommy 老師帶你重新搞懂閉包 Closure](https://www.youtube.com/watch?v=ksmk5RO5DgU)