Guest Adventurer 🥉 Lv.1
🪙 50
🔷 10
← Back to library
Article · programming

JavaScript Functions: สร้างฟังก์ชันให้โค้ดทำงานซ้ำได้

JavaScript

EP 9 ของซีรีส์ JavaScript คืออะไร? เริ่มต้นเขียนโปรแกรม เรียนรู้การสร้างฟังก์ชัน การรับพารามิเตอร์ การส่งค่ากลับ และการนำฟังก์ชันไปประยุกต์ใช้กับข้อมูลจริง

EP 9: Functions หัวใจของการเขียนโปรแกรมที่นำกลับมาใช้ซ้ำได้

จากตอนก่อนที่เราเรียนรู้การจัดเก็บข้อมูลด้วย Array และ Object ตอนนี้จะพาไปรู้จักสิ่งสำคัญอีกอย่างหนึ่งของ JavaScript นั่นคือ **Function หรือฟังก์ชัน** ซึ่งเปรียบเสมือนชุดคำสั่งที่เราสร้างขึ้นเพื่อทำงานเฉพาะอย่าง เมื่อจำเป็นต้องใช้งาน เราสามารถเรียกฟังก์ชันเดิมได้หลายครั้งโดยไม่ต้องเขียนคำสั่งทั้งหมดซ้ำอีก
แนวคิดสำคัญฟังก์ชันช่วยแบ่งโปรแกรมขนาดใหญ่ให้เป็นส่วนย่อยที่เข้าใจง่าย ทดสอบสะดวก และดูแลรักษาได้ง่ายขึ้น โดยแต่ละฟังก์ชันควรมีหน้าที่ชัดเจน

1. ฟังก์ชันคืออะไร?

ลองนึกถึงเครื่องชงกาแฟ เราใส่วัตถุดิบ กดปุ่ม แล้วเครื่องทำงานตามขั้นตอนที่กำหนดไว้ ฟังก์ชันก็มีแนวคิดคล้ายกัน เราสามารถส่งข้อมูลเข้าไป ให้ชุดคำสั่งประมวลผล และรับผลลัพธ์กลับมาได้ ทั้งนี้ ฟังก์ชันบางตัวอาจไม่ต้องรับข้อมูลหรือส่งค่ากลับเลยก็ได้
function sayHello() {
    console.log('สวัสดี JavaScript!');
}

sayHello();
sayHello();
ตัวอย่างนี้สร้างฟังก์ชันชื่อ `sayHello` ด้วยคำสั่ง `function` ภายในมีคำสั่งแสดงข้อความผ่าน `console.log()` เมื่อเรียก `sayHello()` แต่ละครั้ง โปรแกรมจะทำงานตามคำสั่งที่อยู่ในฟังก์ชัน ทำให้ข้อความถูกแสดงสองครั้ง

2. ส่วนประกอบของฟังก์ชัน

ฟังก์ชันแบบประกาศด้วย `function` โดยทั่วไปประกอบด้วยชื่อฟังก์ชัน วงเล็บสำหรับระบุพารามิเตอร์ ปีกกาสำหรับบรรจุชุดคำสั่ง และอาจมี `return` เพื่อส่งผลลัพธ์กลับไปยังจุดที่เรียกใช้งาน
function calculateTotal(price, quantity) {
    const total = price * quantity;
    return total;
}

const result = calculateTotal(120, 3);
console.log(result);
ส่วนประกอบความหมายตัวอย่าง
functionคำสั่งประกาศฟังก์ชันfunction calculateTotal
ชื่อฟังก์ชันชื่อที่ใช้เรียกชุดคำสั่งcalculateTotal
พารามิเตอร์ตัวแปรที่รับข้อมูลเข้ามาprice, quantity
ชุดคำสั่งคำสั่งที่ฟังก์ชันต้องดำเนินการconst total = price * quantity
returnส่งค่าผลลัพธ์กลับไปยังผู้เรียกreturn total

3. พารามิเตอร์และอาร์กิวเมนต์ต่างกันอย่างไร?

**พารามิเตอร์ (Parameter)** คือตัวแปรที่กำหนดไว้ในวงเล็บตอนสร้างฟังก์ชัน ส่วน **อาร์กิวเมนต์ (Argument)** คือค่าจริงที่ส่งเข้ามาตอนเรียกฟังก์ชัน ความแตกต่างนี้ช่วยให้เราเข้าใจว่าฟังก์ชันเดียวกันสามารถรับข้อมูลต่างกันและให้ผลลัพธ์ต่างกันได้
function greet(name) {
    console.log(`สวัสดี ${name}`);
}

greet('มิน');
greet('นัท');
greet('พลอย');
ในตัวอย่าง `name` เป็นพารามิเตอร์ ส่วน `'มิน'`, `'นัท'` และ `'พลอย'` เป็นอาร์กิวเมนต์ ฟังก์ชัน `greet` จึงนำกลับมาใช้กับชื่อที่แตกต่างกันได้โดยไม่ต้องสร้างฟังก์ชันใหม่สำหรับแต่ละคน

กำหนดค่าเริ่มต้นให้พารามิเตอร์

หากต้องการให้ฟังก์ชันมีค่าที่ใช้เมื่อผู้เรียกไม่ได้ส่งอาร์กิวเมนต์มา เราสามารถกำหนด Default Parameter ได้ ช่วยลดกรณีที่ข้อมูลบางส่วนไม่มีค่า
function greetUser(name = 'ผู้ใช้งาน') {
    return `ยินดีต้อนรับ ${name}`;
}

console.log(greetUser('ออม'));
console.log(greetUser());
ผลลัพธ์ที่ควรเข้าใจการเรียก `greetUser('ออม')` ใช้ชื่อออม ส่วน `greetUser()` ใช้ค่าเริ่มต้นว่า ผู้ใช้งาน ค่าเริ่มต้นจะถูกนำมาใช้เมื่ออาร์กิวเมนต์ที่เกี่ยวข้องเป็น `undefined`

4. return สำคัญอย่างไร?

`return` ใช้ส่งค่าจากฟังก์ชันกลับไปยังตำแหน่งที่เรียกใช้งาน และเมื่อโปรแกรมทำงานถึง `return` ฟังก์ชันนั้นจะจบการทำงานทันที หากฟังก์ชันไม่มีคำสั่ง `return` ที่ส่งค่าออกมา ผลลัพธ์ที่ได้รับจะเป็น `undefined`
function add(a, b) {
    return a + b;
}

function addAndPrint(a, b) {
    console.log(a + b);
}

const sum = add(10, 5);
const printed = addAndPrint(10, 5);

console.log('ค่าที่ส่งกลับ:', sum);
console.log('ค่าที่ได้รับ:', printed);
ฟังก์ชัน `add` ส่งผลรวมกลับมา จึงนำค่าไปเก็บในตัวแปร `sum` หรือคำนวณต่อได้ ส่วน `addAndPrint` แสดงผลด้วย `console.log()` เท่านั้นและไม่มี `return` จึงไม่ได้ส่งผลรวมกลับมาให้ตัวแปร `printed`
อย่าสับสนระหว่างการแสดงผลกับการส่งค่ากลับ`console.log()` มีหน้าที่แสดงข้อมูล ส่วน `return` มีหน้าที่ส่งค่ากลับจากฟังก์ชัน ทั้งสองอย่างอาจใช้ร่วมกันได้ แต่ไม่ใช่สิ่งเดียวกัน

5. Function Declaration และ Function Expression

JavaScript มีหลายวิธีในการสร้างฟังก์ชัน รูปแบบแรกคือ Function Declaration ซึ่งประกาศด้วย `function` และมีชื่อฟังก์ชันโดยตรง ส่วน Function Expression คือการนำฟังก์ชันไปกำหนดให้ตัวแปร ทั้งสองรูปแบบใช้สร้างพฤติกรรมที่ต้องการได้ แต่มีรายละเอียดด้านการประกาศและการเรียกใช้แตกต่างกัน
function square(number) {
    return number * number;
}

const cube = function (number) {
    return number * number * number;
};

console.log(square(4));
console.log(cube(3));
ตัวอย่างแรกประกาศฟังก์ชันชื่อ `square` โดยตรง ส่วนตัวอย่างที่สองสร้างฟังก์ชันแล้วเก็บไว้ในตัวแปร `cube` เมื่อใช้ Function Expression ที่กำหนดให้ตัวแปรด้วย `const` ต้องประกาศตัวแปรก่อนเรียกใช้งาน

6. Arrow Function รูปแบบกระชับที่นิยมใช้

Arrow Function ใช้เครื่องหมาย `=>` เพื่อสร้างฟังก์ชันในรูปแบบที่กระชับ มักพบในการเขียน JavaScript สมัยใหม่ โดยเฉพาะฟังก์ชันที่ส่งให้เมธอดของ Array เช่น `map()` และ `filter()`
const double = number => number * 2;
const add = (a, b) => a + b;
const isAdult = age => age >= 18;

console.log(double(6));
console.log(add(7, 8));
console.log(isAdult(20));
เมื่อ Arrow Function มีนิพจน์เดียวและไม่ใช้ปีกกา สามารถละคำว่า `return` ได้ เพราะจะส่งค่านิพจน์นั้นกลับโดยอัตโนมัติ หากใช้ปีกกาเพื่อเขียนชุดคำสั่งหลายบรรทัด ต้องเขียน `return` เองเมื่อจำเป็นต้องส่งค่ากลับ
const calculateDiscount = (price, percent) => {
    const discount = price * percent / 100;
    const finalPrice = price - discount;
    return finalPrice;
};

console.log(calculateDiscount(1000, 15));

7. นำฟังก์ชันไปทำงานร่วมกับ Array

ฟังก์ชันมีประโยชน์มากเมื่อใช้กับข้อมูลหลายรายการ เราสามารถนำ Arrow Function ไปใช้กับ `map()` เพื่อแปลงข้อมูลแต่ละรายการ หรือใช้ `filter()` เพื่อเลือกเฉพาะรายการที่ผ่านเงื่อนไข ซึ่งเป็นการต่อยอดความรู้จากตอน Arrays ได้อย่างเป็นธรรมชาติ
const prices = [100, 250, 80, 400, 150];

const pricesWithVat = prices.map(price => price * 1.07);
const expensivePrices = prices.filter(price => price >= 200);
const totalPrice = prices.reduce((sum, price) => sum + price, 0);

console.log('ราคาพร้อม VAT:', pricesWithVat);
console.log('ราคาตั้งแต่ 200 ขึ้นไป:', expensivePrices);
console.log('ราคารวม:', totalPrice);
เมธอดหน้าที่ผลลัพธ์ที่ได้
map()แปลงแต่ละรายการArray ใหม่ที่มีค่าจากการแปลง
filter()เลือกข้อมูลตามเงื่อนไขArray ใหม่ที่มีเฉพาะรายการที่ผ่านเงื่อนไข
reduce()รวมข้อมูลให้เป็นผลลัพธ์เดียวค่าเดียว เช่น ผลรวม

8. ขอบเขตตัวแปรกับฟังก์ชัน

ตัวแปรที่ประกาศภายในฟังก์ชันด้วย `let` หรือ `const` จะอยู่ในขอบเขตของบล็อกที่ประกาศ ตัวแปรเหล่านี้ไม่สามารถเรียกใช้จากภายนอกฟังก์ชันได้โดยตรง การแยกขอบเขตช่วยป้องกันไม่ให้ข้อมูลภายในไปชนกับตัวแปรอื่นโดยไม่ตั้งใจ
const message = 'ข้อความจากภายนอก';

function showMessage() {
    const localMessage = 'ข้อความภายในฟังก์ชัน';
    console.log(message);
    console.log(localMessage);
}

showMessage();
console.log(message);
// console.log(localMessage); จะเกิด ReferenceError
ตัวแปร `message` ถูกประกาศภายนอกฟังก์ชัน จึงเข้าถึงได้ในตัวอย่างนี้ทั้งจากภายนอกและภายในฟังก์ชัน ส่วน `localMessage` ถูกประกาศภายใน `showMessage` จึงไม่สามารถเข้าถึงจากภายนอกได้

9. ตัวอย่างประยุกต์: คำนวณยอดสั่งซื้อ

สมมติว่าเรากำลังพัฒนาระบบร้านค้าออนไลน์ มีรายการสินค้าเก็บอยู่ใน Array ของ Object เราสามารถสร้างฟังก์ชันสำหรับคำนวณราคารวม ส่วนลด และยอดชำระสุทธิ แทนการเขียนสูตรเดิมซ้ำในหลายหน้าของระบบ
const cart = [
    { name: 'สมุด', price: 35, quantity: 2 },
    { name: 'ปากกา', price: 12, quantity: 5 },
    { name: 'กระเป๋า', price: 450, quantity: 1 }
];

function calculateSubtotal(items) {
    return items.reduce((sum, item) => {
        return sum + item.price * item.quantity;
    }, 0);
}

function calculateDiscount(subtotal, percent = 0) {
    return subtotal * percent / 100;
}

function calculateOrder(items, discountPercent = 0) {
    const subtotal = calculateSubtotal(items);
    const discount = calculateDiscount(subtotal, discountPercent);

    return {
        subtotal,
        discount,
        total: subtotal - discount
    };
}

const order = calculateOrder(cart, 10);
console.log('ยอดก่อนหักส่วนลด:', order.subtotal);
console.log('ส่วนลด:', order.discount);
console.log('ยอดชำระสุทธิ:', order.total);
ตัวอย่างนี้แยกความรับผิดชอบเป็นสามส่วน ได้แก่ การหายอดรวมสินค้า การคำนวณส่วนลด และการรวมผลลัพธ์ของคำสั่งซื้อ แต่ละฟังก์ชันสามารถนำไปทดสอบหรือปรับปรุงแยกกันได้ หากระบบต้องเพิ่มภาษี ค่าจัดส่ง หรือคูปองส่วนลด ก็สามารถต่อยอดได้ง่ายกว่าเขียนทุกอย่างรวมกันในฟังก์ชันเดียว
ข้อควรระวังในระบบเงินจริงตัวอย่างนี้ใช้ตัวเลข JavaScript ทั่วไปเพื่อการเรียนรู้ ระบบการเงินที่ต้องการความแม่นยำควรออกแบบการเก็บจำนวนเงินอย่างเหมาะสม เช่น ใช้หน่วยย่อยจำนวนเต็มหรือไลบรารีคำนวณทศนิยม และตรวจสอบข้อมูลที่รับเข้ามาก่อนคำนวณ

10. แนวทางเขียนฟังก์ชันที่ดี

ฟังก์ชันที่ดีไม่จำเป็นต้องสั้นที่สุด แต่ควรมีหน้าที่ชัดเจน ตั้งชื่อให้สื่อความหมาย รับเฉพาะข้อมูลที่จำเป็น และส่งผลลัพธ์ในรูปแบบที่ผู้เรียกเข้าใจได้ การแยกงานออกเป็นฟังก์ชันย่อยช่วยลดการทำซ้ำและทำให้ตรวจหาข้อผิดพลาดได้ง่ายขึ้น
แนวทางตัวอย่างที่ควรเลือกเหตุผล
ตั้งชื่อให้สื่อความหมายcalculateTotal()อ่านแล้วเข้าใจหน้าที่
ทำหน้าที่เดียวให้ชัดเจนvalidateEmail()ทดสอบและปรับปรุงง่าย
ลดโค้ดที่ซ้ำกันเรียกฟังก์ชันเดิมหลายครั้งลดความคลาดเคลื่อนจากการแก้หลายจุด
ตรวจสอบข้อมูลนำเข้าตรวจว่าราคาเป็นตัวเลขป้องกันข้อมูลผิดรูปแบบ
ส่งค่ากลับอย่างสม่ำเสมอreturn object หรือค่าที่กำหนดผู้เรียกนำผลลัพธ์ไปใช้ต่อได้

11. แบบฝึกหัดท้ายบท

ลองเขียนฟังก์ชันด้วยตนเองก่อนดูแนวทางเฉลย เป้าหมายคือฝึกเลือกพารามิเตอร์ เขียนสูตรภายในฟังก์ชัน และใช้ `return` เพื่อส่งผลลัพธ์กลับ
โจทย์ที่ 1: สร้างฟังก์ชันหาพื้นที่สี่เหลี่ยมผืนผ้า
สร้างฟังก์ชันชื่อ `rectangleArea(width, height)` รับความกว้างและความสูง แล้วส่งค่าพื้นที่กลับมา ทดลองเรียกด้วย `rectangleArea(8, 5)` ซึ่งควรได้ผลลัพธ์ 40
function rectangleArea(width, height) {
    return width * height;
}

console.log(rectangleArea(8, 5));
โจทย์ที่ 2: ตรวจสอบว่าตัวเลขเป็นเลขคู่หรือไม่
สร้างฟังก์ชัน `isEven(number)` ที่ส่งค่า `true` เมื่อจำนวนเต็มหารด้วย 2 ลงตัว และส่งค่า `false` เมื่อเป็นเลขคี่ ลองทดสอบด้วยเลข 12 และ 7
function isEven(number) {
    return Number.isInteger(number) && number % 2 === 0;
}

console.log(isEven(12));
console.log(isEven(7));
console.log(isEven(4.5));
โจทย์ที่ 3: คำนวณราคาเฉลี่ย
สร้างฟังก์ชัน `average(numbers)` รับ Array ของตัวเลข แล้วส่งค่าเฉลี่ยกลับมา ควรตรวจสอบกรณี Array ว่างเพื่อไม่ให้เกิดการหารด้วยศูนย์
function average(numbers) {
    if (numbers.length === 0) {
        return null;
    }

    const total = numbers.reduce((sum, number) => sum + number, 0);
    return total / numbers.length;
}

console.log(average([10, 20, 30]));
console.log(average([]));

12. สรุปบทเรียนและเตรียมตัวสู่ตอนถัดไป

ในตอนนี้เราได้เรียนรู้การประกาศฟังก์ชัน การรับพารามิเตอร์ การกำหนดค่าเริ่มต้น การส่งค่าด้วย `return` รูปแบบ Function Expression และ Arrow Function รวมถึงการนำฟังก์ชันไปใช้กับ Array และ Object ความเข้าใจเหล่านี้เป็นพื้นฐานสำคัญของการพัฒนาโปรแกรม JavaScript ที่มีโครงสร้างชัดเจน
เขียนโค้ดให้ทำงานได้คือจุดเริ่มต้น แต่การแบ่งงานให้ชัดเจนและนำกลับมาใช้ซ้ำได้ คือก้าวสำคัญของการเขียนโปรแกรมอย่างมีคุณภาพ
ตอนต่อไป: Scope และ Closureเมื่อรู้จักฟังก์ชันแล้ว ตอนถัดไปจะต่อยอดด้วยเรื่องขอบเขตของตัวแปร (Scope) และ Closure เพื่อทำความเข้าใจว่าฟังก์ชันเข้าถึงข้อมูลจากบริบทภายนอกได้อย่างไร และความรู้นี้นำไปใช้สร้างโครงสร้างโปรแกรมที่ยืดหยุ่นขึ้นได้อย่างไร

ทบทวนด้วยการลองเปลี่ยนค่าที่ส่งเข้าไปในฟังก์ชันทุกตัว แล้วสังเกตผลลัพธ์ที่เปลี่ยนแปลง เมื่อสามารถอธิบายได้ว่าแต่ละฟังก์ชันรับข้อมูลอะไร ประมวลผลอย่างไร และส่งค่าใดกลับมา แสดงว่าคุณเริ่มพร้อมสำหรับการเขียนโปรแกรมที่ซับซ้อนขึ้นแล้ว
Reach within 500px of the page end and stay for at least 5 minutes to earn EXP once per day.

⏳ Reading timer is running...

🌐
Select Language
21 World Languages Supported