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

:::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)