# Functions

## Function คืออะไร ?

คือ ชุดคำสั่งที่รวมคำสั่งอื่น ๆ เอาไว้ เมื่อเรียกใช้งานแล้วจะทำคำสั่งภายในตัวมันเองจนเสร็จ

โดยเราสามารถกำหนดให้ function รับค่าเพื่อนำมาใช้ภายในตัว function ได้ และเราจะส่งค่ากลับไปยัง code ส่วนที่เรียกใช้หรือไม่ก็ได้

{% hint style="warning" %}
ทุกอย่างที่เราประกาศข้างใน function จะหายไปเมื่อ function จบการทำงาน
{% endhint %}

```javascript
function sum(a, b) {
    const result = a + b;
    return result;
}
 
console.log(sum(5, 27)); // 32
```

จากตัวอย่าง เราต้องการรับค่า `a` และ `b`  มาใช้ภายใน function จากนั้นเราคำนวณผลบวกของ `a` และ `b` แล้วส่งค่ากลับไปยัง code ที่เรียกใช้ function ด้วยคำสั่ง `return`

#### Parameter และ Argument คืออะไร ?

* parameter คือ ค่าที่ function ต้องการจะรับ (จากตัวอย่างข้างบน คือ `a` และ `b`)
* argument คือ ค่าที่ function ได้รับตอนถูกเรียกใช้ (จากตัวอย่างข้างบน คือ 5 และ 27)

## การรับ object หรือ array มาใช้ใน function

หากค่าที่ function รับมาเป็น object หรือ array แล้วเราแก้ไขโดยตรง ค่าที่อยู่ข้างในจะถูกแก้ไขไปด้วย

```javascript
function dyeCat(cat, color) {
    cat.color = color;
}
 
let myCat = {
    color: "black";
};
 
dyeCat(myCat, "red");
console.log(myCat); // {color: "red"}
```

## Nested functions

เราสามารถประกาศ function ภายใน function ได้

โดย function ข้างในสามารถเข้าถึงค่าที่อยู่ข้างนอกได้ และสามารถเรียกใช้ได้จากภายใน function ที่ประกาศตัวมันขึ้นมาเท่านั้น

```javascript
function outerKrub() {
    let msg = "Hello from outerKrub";
 
    function innerKrub() {
        console.log(msg);
    }
 
    innerKrub(); // Hello from outerKrub
}
 
outerKrub();
innerKrub(); // innerKrub is not defined
```

### Closures

JavaScript จะสร้างสิ่งที่เรียกว่า closure เมื่อมีการประกาศ nested function โดยเป็นเหมือนกับการผูกค่าหรือตัวแปรของ function ข้างนอกไว้กับ function ข้างใน

ทำให้ function ข้างในสามารถเข้าถึงค่าของ function ที่อยู่ข้างนอกได้ แม้ว่า function ข้างนอกจะทำงานเสร็จไปแล้ว

```javascript
function outerKrub() {
    let msg = "Hello from outerKrub";
 
    function innerKrub() { // A closure
        console.log(msg); // Hello from outerKrub
    }
 
    return innerKrub;
}
 
let callLaterNa = outerKrub();
callLaterNa(); // Hello from outerKrub
```

จากตัวอย่างเรา return `innerKrub` ที่เป็น function ออกมาเพื่อเรียกใช้นอก `outerKrub` โดยใช้ชื่อว่า `callLaterNa`

เมื่อเรียกใช้ `callLaterNa` จะพบว่ายังคงเข้าถึงค่า `msg` ที่ประกาศใน `outerKrub` ได้อยู่ แม้ว่า `outerKrub` จะทำงานเสร็จไปแล้ว

## Arrow functions

เป็น expression แบบสั้น ๆ สำหรับใช้ประกาศ function

```javascript
// Function
function sumOne(a, b) {
    return a + b;
}
 
// Arrow functions
const sumTwo = (a, b) => {
    return a + b;
}
 
const sumThree = (a, b) => a + b;
 
console.log(sumOne(27, 5));   // 32
console.log(sumTwo(27, 5));   // 32
console.log(sumThree(27, 5)); // 32
```

จากตัวอย่าง ถ้าใน function มีเพียง `return` statement เราสามารถนำค่าที่จะ return มาวางหลัง `=>` ได้เลย

### รูปแบบการใช้งาน

* มี parameter ตัวเดียว ไม่ต้องใส่ `( )`

```javascript
param => expression
```

* ไม่มี parameter หรือมี parameter 2 ตัวขึ้นไป ต้องใส่ `( )`

```javascript
() => expression
(param1, param2) => expression
```

* ใน function ที่มีมากกว่า 1 statement ต้องใส่ `{ }` และ `return`

```javascript
param => {
    console.log("Squared!");
    return param * param;
}
```

## แหล่งอ้างอิง 📑

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions>" %}
