JavaScript
Advanced Concepts
Modules (import / export)
เรียนรู้ ES6 Modules เพื่อแก้ปัญหา global scope pollution ทำความเข้าใจ named export, default export, import syntax, aliasing และ barrel file pattern
ปัญหาที่ Modules แก้ได้
ในยุคแรกของ JavaScript ทุกอย่างอยู่ใน global scope — ถ้ามีไฟล์หลายไฟล์ ตัวแปรและฟังก์ชันจะชนกัน (name collision) ES6 Modules แก้ปัญหานี้ด้วยการทำให้ทุกไฟล์มี **scope เป็นของตัวเอง** ต้องใช้ `export` เพื่อแชร์สิ่งที่ต้องการ และ `import` เพื่อนำมาใช้
| ปัญหา (ก่อน modules) | แก้ได้ด้วย modules |
|---|---|
| ตัวแปร global ชนกัน | แต่ละไฟล์มี scope เป็นของตัวเอง |
| ไม่รู้ว่าโค้ดพึ่งพาอะไร | ดู import statement รู้ได้ทันที |
| โหลด script ผิดลำดับ | ระบบ module จัดการ dependency ให้ |
| ไม่มีการ encapsulate | export เฉพาะสิ่งที่ต้องการแชร์ |
Mental Model: Toolbox
ลองนึกว่าแต่ละไฟล์ `.js` คือ **กล่องเครื่องมือ** ที่ล็อคอยู่ `export` คือการวางเครื่องมือไว้ด้านนอกกล่อง ให้คนอื่นหยิบไปใช้ได้ `import` คือการบอกว่า "ฉันต้องการเครื่องมือชิ้นนี้จากกล่องนั้น" เครื่องมือที่ไม่ได้ `export` จะยังคงอยู่ใน private scope ของไฟล์นั้น
Named Export — ส่งออกหลายรายการ
Named export ส่งออกสิ่งต่างๆ พร้อมชื่อ — ผู้ import ต้องใช้ชื่อเดิม (หรือ alias ด้วย `as`)
// --- math.js ---
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// ส่งออกทีเดียวหลายรายการก็ได้
const subtract = (a, b) => a - b;
const divide = (a, b) => a / b;
export { subtract, divide };// --- main.js ---
import { PI, add, multiply } from './math.js';
console.log(PI); // 3.14159
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
// ใช้ alias เมื่อชื่อชนกัน
import { add as mathAdd } from './math.js';Default Export — ส่งออกค่าหลัก
แต่ละไฟล์มี default export ได้ **1 ตัวเท่านั้น** — ผู้ import ตั้งชื่อเองได้เลยโดยไม่ต้องใช้วงเล็บปีกกา
// --- greeting.js ---
export default function greet(name) {
return "สวัสดี " + name;
}
// หรือ
const farewell = (name) => "ลาก่อน " + name;
export default farewell;// --- main.js ---
import greet from './greeting.js'; // ตั้งชื่อเองได้
import sayBye from './greeting.js'; // หรือชื่ออื่น
console.log(greet("Alice")); // "สวัสดี Alice"
console.log(sayBye("Alice")); // "ลาก่อน Alice"Named vs Default Export
| Named Export | Default Export | |
|---|---|---|
| จำนวนต่อไฟล์ | ไม่จำกัด | 1 ตัวเท่านั้น |
| Syntax ส่งออก | export const x = ... | export default ... |
| Syntax import | import { x } from ... | import x from ... |
| ต้องใช้ชื่อเดิม? | ใช่ (หรือ alias ด้วย as) | ไม่ — ตั้งชื่อเองได้ |
| ใช้เมื่อ | ส่งออกหลายสิ่ง | ส่งออก 1 สิ่งหลัก (เช่น class, component) |
Re-export และ Barrel File
**Barrel file** คือไฟล์ `index.js` ที่รวบรวม export จากหลายไฟล์ไว้ที่เดียว ทำให้ import สะดวกขึ้น
// --- utils/format.js ---
export function formatDate(date) { return date.toLocaleDateString(); }
// --- utils/validate.js ---
export function isEmail(str) { return str.includes('@'); }
// --- utils/index.js (barrel file) ---
export { formatDate } from './format.js';
export { isEmail } from './validate.js';
// --- main.js ---
// import จาก barrel ได้เลย แทนที่จะ import จากแต่ละไฟล์
import { formatDate, isEmail } from './utils/index.js';สรุป
- ES6 Modules ทำให้แต่ละไฟล์มี scope เป็นของตัวเอง แก้ปัญหา global scope pollution
- Named export: export หลายรายการ ผู้ import ต้องใช้ชื่อเดิม (หรือ as alias)
- Default export: ไฟล์ละ 1 ตัว ผู้ import ตั้งชื่อเองได้
- import { x, y } from './file.js' สำหรับ named, import x from './file.js' สำหรับ default
- Barrel file (index.js) รวบรวม export ไว้ที่เดียว ทำให้ import สะดวก