บทที่ 3 JavaScript และ Modern Front-end

สไลด์บทเรียน

วัตถุประสงค์

  1. อธิบายบทบาทของ JavaScript ในการสร้างหน้าเว็บแบบ interactive ได้
  2. ใช้ ES6+, Variable, Function, Arrow Function และ Module ได้อย่างเหมาะสม
  3. จัดการ DOM และ Event เพื่อเปลี่ยนเนื้อหาบนหน้าเว็บตามการกระทำของผู้ใช้ได้
  4. ใช้ Fetch API และ Async/Await เพื่อดึงข้อมูลจาก API ได้
  5. สร้างหน้าเว็บที่ค้นหา กรอง และแสดงข้อมูลจาก API จำลองได้

ภาพรวมบทเรียน

บทก่อนหน้าเน้นการสร้างโครงสร้างและหน้าตาด้วย HTML5 และ CSS3 ส่วนบทนี้จะเพิ่มความสามารถด้านพฤติกรรมของหน้าเว็บด้วย JavaScript เช่น คลิกปุ่มแล้วเปลี่ยนข้อมูล ตรวจสอบฟอร์ม โหลดรายการจาก API และอัปเดตหน้าเว็บโดยไม่ต้อง reload

คำสำคัญของบทเรียน


1. บทบาทของ JavaScript ใน Modern Front-end

JavaScript ทำหน้าที่เชื่อมระหว่างโครงสร้างหน้าเว็บ ข้อมูล และการกระทำของผู้ใช้ เมื่อผู้ใช้คลิกปุ่ม พิมพ์ข้อความ ส่งฟอร์ม หรือเลือกตัวกรอง JavaScript จะรับ event แล้วสั่งให้หน้าเว็บอัปเดตเฉพาะส่วนที่เกี่ยวข้อง

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#83a598',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
flowchart LR
  A[User Action
การกระทำของผู้ใช้] --> B[Event Listener
ตัวรับเหตุการณ์] B --> C[JavaScript Logic
ตรรกะของโปรแกรม] C --> D[DOM Update
อัปเดตหน้าเว็บ] C --> E[Fetch API
ดึงข้อมูลจาก API] E --> D

ตัวอย่างงานที่ JavaScript ทำบนหน้าเว็บ

งาน ตัวอย่าง
เปลี่ยนเนื้อหา แสดงข้อความต้อนรับหลังผู้ใช้กรอกชื่อ
ตรวจสอบฟอร์ม ตรวจว่าอีเมลถูกต้องก่อนส่ง
จัดการรายการ เพิ่ม ลบ ค้นหา หรือกรองข้อมูล
ติดต่อ API โหลดสินค้า ข่าว หรือข้อมูลผู้ใช้จาก server
ปรับประสบการณ์ผู้ใช้ แสดง loading, error message หรือ notification

2. Variable: let, const และ var

Variable คือชื่อที่ใช้เก็บข้อมูลเพื่อนำไปใช้ต่อในโปรแกรม ใน JavaScript สมัยใหม่ควรใช้ const เป็นค่าเริ่มต้น และใช้ let เมื่อต้องเปลี่ยนค่า ส่วน var เป็นรูปแบบเก่าที่ควรหลีกเลี่ยงในงานใหม่ เพราะ scope ทำให้สับสนได้ง่าย

คำสั่ง ใช้เมื่อ เปลี่ยนค่าได้หรือไม่ ขอบเขต
const ค่าที่ไม่ต้องกำหนดใหม่ ไม่ได้ Block scope
let ค่าที่ต้องเปลี่ยนระหว่างทำงาน ได้ Block scope
var โค้ดเก่า ได้ Function scope
// ใช้ const เมื่อค่าหลักไม่ต้อง assign ใหม่
const courseName = 'Web Application Development';

// ใช้ let เมื่อต้องเปลี่ยนค่า
let learnerCount = 25;
learnerCount = learnerCount + 1;

console.log(`${courseName}: ${learnerCount} learners`);

3. Function และ Arrow Function

Function คือชุดคำสั่งที่นำกลับมาใช้ซ้ำได้ ช่วยให้โค้ดอ่านง่ายและแยกหน้าที่ชัดเจน ส่วน Arrow Function เป็นรูปแบบการเขียน function ที่สั้นลง เหมาะกับ callback, array method และ event handler

// Function ปกติ เหมาะกับงานที่ต้องการชื่อชัดเจน
function calculateTotal(price, quantity) {
  return price * quantity;
}

// Arrow Function เหมาะกับ callback หรือ logic สั้น ๆ
const formatCurrency = (amount) => `${amount.toLocaleString()} บาท`;

const total = calculateTotal(120, 3);
console.log(formatCurrency(total));

เปรียบเทียบรูปแบบ Function

รูปแบบ จุดเด่น เหมาะกับ
Function Declaration อ่านง่าย เรียกใช้ก่อนประกาศได้ ฟังก์ชันหลักของโปรแกรม
Function Expression เก็บในตัวแปรได้ ส่งต่อเป็นค่า
Arrow Function สั้น กระชับ callback และ array method

4. Array Method สำหรับจัดการข้อมูล

ในงาน front-end มักได้รับข้อมูลเป็น array เช่น รายการสินค้า รายชื่อนักศึกษา หรือโพสต์จาก API เครื่องมือสำคัญคือ map, filter, find และ reduce

const products = [
  { id: 1, name: 'Keyboard', price: 850, category: 'device' },
  { id: 2, name: 'Mouse', price: 420, category: 'device' },
  { id: 3, name: 'JavaScript Book', price: 390, category: 'book' }
];

// filter ใช้คัดเฉพาะข้อมูลที่ตรงเงื่อนไข
const devices = products.filter((product) => product.category === 'device');

// map ใช้แปลงข้อมูลเป็นรูปแบบใหม่
const productNames = devices.map((product) => product.name);

console.log(productNames);
Method หน้าที่ ตัวอย่างการใช้
map แปลงข้อมูลทุกตัว สร้าง HTML card จากรายการสินค้า
filter คัดข้อมูลตามเงื่อนไข กรองสินค้าเฉพาะหมวด
find หา item แรกที่ตรงเงื่อนไข ค้นหาสินค้าจาก id
reduce รวมค่าทั้งหมด รวมราคาสินค้าในตะกร้า

5. DOM: การเข้าถึงและแก้ไขหน้าเว็บ

DOM หรือ Document Object Model คือโครงสร้างของหน้า HTML ที่ browser แปลงเป็น object ทำให้ JavaScript สามารถเลือก element แก้ไขข้อความ เพิ่ม class หรือสร้าง element ใหม่ได้

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#b8bb26',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
flowchart TD
  A[document
เอกสาร] --> B[html
รากของหน้า] B --> C[head
ข้อมูลหน้า] B --> D[body
เนื้อหาที่แสดง] D --> E[main
เนื้อหาหลัก] E --> F[button
ปุ่ม] E --> G[section
พื้นที่แสดงผล]
<h2 id="title">รายการสินค้า</h2>
<button id="loadButton">โหลดข้อมูล</button>
<p id="status">ยังไม่ได้โหลดข้อมูล</p>

<script>
  // เลือก element จาก id
  const loadButton = document.querySelector('#loadButton');
  const statusText = document.querySelector('#status');

  // เปลี่ยนข้อความเมื่อผู้ใช้คลิกปุ่ม
  loadButton.addEventListener('click', () => {
    statusText.textContent = 'กำลังโหลดข้อมูล...';
  });
</script>

6. Event: การตอบสนองต่อผู้ใช้

Event คือเหตุการณ์ที่เกิดขึ้นบนหน้าเว็บ เช่น click, input, submit, change หรือ keydown การใช้ event listener ทำให้หน้าเว็บตอบสนองต่อผู้ใช้ได้ทันที

<form id="searchForm">
  <label for="keyword">ค้นหา</label>
  <input id="keyword" name="keyword" type="search" required>
  <button type="submit">ค้นหา</button>
</form>

<p id="result"></p>

<script>
  const form = document.querySelector('#searchForm');
  const keywordInput = document.querySelector('#keyword');
  const result = document.querySelector('#result');

  form.addEventListener('submit', (event) => {
    // ป้องกัน browser reload หน้าเมื่อ submit form
    event.preventDefault();

    result.textContent = `คำค้นหา: ${keywordInput.value}`;
  });
</script>
Event เกิดเมื่อ ใช้กับ
click ผู้ใช้คลิก ปุ่ม เมนู card
input ค่าช่องกรอกเปลี่ยน search, form validation
submit ส่งฟอร์ม login, register, search
change เลือกค่าใหม่ select, checkbox, radio
keydown กดแป้นพิมพ์ shortcut, search suggestion

7. Module: แยกโค้ดให้ดูแลง่าย

Module ช่วยแยกโค้ดเป็นไฟล์ย่อยตามหน้าที่ เช่น ไฟล์จัดการ API ไฟล์จัดการ DOM และไฟล์หลักของหน้าเว็บ ทำให้โค้ดอ่านง่าย ทดสอบง่าย และนำกลับมาใช้ซ้ำได้

// api.js
export async function getProducts() {
  const response = await fetch('/api/products.json');
  return response.json();
}
// app.js
import { getProducts } from './api.js';

const products = await getProducts();
console.log(products);
<!-- ต้องระบุ type="module" เพื่อให้ browser ใช้ import/export ได้ -->
<script type="module" src="app.js"></script>

8. Fetch API และ Async/Await

การติดต่อ API เป็นงานสำคัญของ modern front-end เพราะข้อมูลจำนวนมากมาจาก server เช่น รายการสินค้า โปรไฟล์ผู้ใช้ หรือผลการค้นหา Fetch API ใช้ส่ง request ส่วน Async/Await ทำให้โค้ด asynchronous อ่านเป็นลำดับได้ง่ายขึ้น

%%{init: {'theme': 'base', 'themeVariables': {
  'background': '#282828',
  'primaryColor': '#3c3836',
  'primaryTextColor': '#fbf1c7',
  'primaryBorderColor': '#fabd2f',
  'lineColor': '#d3869b',
  'secondaryColor': '#504945',
  'tertiaryColor': '#665c54',
  'fontFamily': 'Arial'
}}}%%
sequenceDiagram
  participant U as User
ผู้ใช้ participant B as Browser
เบราว์เซอร์ participant A as API
บริการข้อมูล U->>B: Click Load Data B->>A: fetch('/api/products') A-->>B: JSON Response B-->>U: Render Cards
async function loadProducts() {
  try {
    const response = await fetch('/api/products.json');

    if (!response.ok) {
      throw new Error('ไม่สามารถโหลดข้อมูลได้');
    }

    const products = await response.json();
    return products;
  } catch (error) {
    console.error(error.message);
    return [];
  }
}

เวลาในการแสดงข้อมูลโดยประมาณ

T=N+P+R

9. ตัวอย่าง Mini App: ค้นหาและกรองรายการจากข้อมูลจำลอง

ตัวอย่างนี้รวม DOM, Event, Array Method และ Async/Await เพื่อสร้างรายการข้อมูลที่ค้นหาได้ โดยใช้ข้อมูลจำลองแทน API จริง

<main>
  <h1>Product Explorer</h1>

  <form id="searchForm">
    <label for="keyword">ค้นหาสินค้า</label>
    <input id="keyword" type="search" placeholder="เช่น keyboard">
    <button type="submit">ค้นหา</button>
  </form>

  <p id="status">พร้อมค้นหา</p>
  <section id="productList" aria-label="รายการสินค้า"></section>
</main>

<script>
  const products = [
    { name: 'Keyboard', price: 850, category: 'Device' },
    { name: 'Mouse', price: 420, category: 'Device' },
    { name: 'JavaScript Book', price: 390, category: 'Book' }
  ];

  const form = document.querySelector('#searchForm');
  const keywordInput = document.querySelector('#keyword');
  const statusText = document.querySelector('#status');
  const productList = document.querySelector('#productList');

  function renderProducts(items) {
    productList.innerHTML = items
      .map((item) => `
        <article>
          <h2>${item.name}</h2>
          <p>${item.category}</p>
          <strong>${item.price} บาท</strong>
        </article>
      `)
      .join('');

    statusText.textContent = `พบข้อมูล ${items.length} รายการ`;
  }

  form.addEventListener('submit', (event) => {
    event.preventDefault();

    const keyword = keywordInput.value.toLowerCase();
    const filteredProducts = products.filter((product) =>
      product.name.toLowerCase().includes(keyword)
    );

    renderProducts(filteredProducts);
  });

  renderProducts(products);
</script>

Checklist ก่อนส่งงานบทที่ 3

รายการตรวจ คำถามที่ต้องตอบ
Variable ใช้ const และ let เหมาะสมหรือไม่
Function แยก logic เป็น function ที่อ่านง่ายหรือไม่
DOM เลือก element ด้วย selector ที่ชัดเจนหรือไม่
Event ใช้ addEventListener และ preventDefault ถูกที่หรือไม่
Fetch จัดการ loading/error เมื่อเรียก API หรือไม่
Rendering อัปเดต DOM เฉพาะส่วนที่จำเป็นหรือไม่
Maintainability โค้ดแบ่งหน้าที่และตั้งชื่ออ่านเข้าใจหรือไม่

กิจกรรม

สร้างหน้าเว็บ Product Explorer หรือ Student Directory ที่มีความสามารถต่อไปนี้:

  1. โหลดข้อมูลจาก API จำลองหรือ array จำลอง
  2. แสดงรายการข้อมูลเป็น card
  3. มีช่องค้นหาและปุ่มค้นหา
  4. กรองข้อมูลด้วย filter
  5. แสดงจำนวนผลลัพธ์ที่พบ
  6. แสดงข้อความเมื่อไม่พบข้อมูล

คำถามทบทวน

  1. let, const และ var ต่างกันอย่างไร
  2. DOM ช่วยให้ JavaScript เปลี่ยนหน้าเว็บได้อย่างไร
  3. addEventListener สำคัญต่อหน้าเว็บแบบ interactive อย่างไร
  4. map และ filter ต่างกันอย่างไร
  5. async/await ช่วยให้โค้ดติดต่อ API อ่านง่ายขึ้นอย่างไร

กลับรายวิชา