JavaScript
Import / Export
ES import ขั้นสูง — default, alias, namespace
เรียนรู้ import ขั้นสูง — default export, alias, และ namespace import เพื่อเขียน module อย่างยืดหยุ่น
named export vs default export — รู้จักทั้ง 2 ระบบ
ในบท import-module เราเรียนการ import แบบ **named** ไปแล้ว: - `import { add, multiply } from './math.js'` — ใช้กับ **named export** ตัวอย่าง named export ที่เราเห็นมาแล้ว (เนื้อหา export เต็มรูปแบบจะเรียนในบท export-module): ```javascript // math.js — named export export function add(a, b) { return a + b; } export function multiply(a, b) { return a * b; } ``` บทนี้เราจะเรียนการ **import** อีกแบบ: import ค่าจาก **default export** — module ที่มีค่า export หลักเพียงค่าเดียว ก่อนจะ import default ได้ เรามาดูกันก่อนว่า default export หน้าตาเป็นยังไง — แล้วหัวข้อถัด ๆ ไปจะโฟกัสที่วิธี import ทั้งหมด
// Named export — หลายค่า ต้องใช้ { } ตอน import
// math.js
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// main.js — ต้องใช้ { } และระบุชื่อทุกตัว
import { add, multiply } from './math.js';
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
// Default export — ค่าหลักเดียว ไม่ต้องใช้ { } ตอน import
// calculator.js
export default function calculate(a, b) {
return a + b;
}
// main.js — import โดยไม่ต้องใช้ { }
import calculate from './calculator.js';
console.log(calculate(5, 3)); // 8Default export ใช้ `export default` เขียนได้หลายแบบ: ```javascript export default "ข้อความ"; // ค่าโดยตรง export default function name() { ... } // function export default class Name { ... } // class export default PI; // ตัวแปรที่ประกาศไว้ก่อน ``` module หนึ่งมี default export ได้ **เพียง 1 ค่า** (แต่มี named export ได้หลายค่า) **Default export เหมือน "สินค้าหลักของร้าน"** — มีชิ้นเดียวเด่นชัด ร้านเดียวกันมีของอื่นขายด้วย (named export) แต่ default คือของหลักที่คนนึกถึง เมื่อรู้แล้วว่า default export หน้าตาเป็นยังไง — หัวข้อถัดไปเราจะเรียนวิธี **import** มัน
- **Named export** — export หลายค่า ต้องใช้ `{ }` ตอน import — เรียนในบท export-module
- **Default export** — export ค่าหลักเดียว ไม่ต้องใช้ `{ }` ตอน import — เรียนวิธี import ในหัวข้อถัดไป
- Module หนึ่งมี default export ได้เพียง 1 ค่า แต่มี named export ได้หลายค่า
- Default export มักใช้เมื่อ module มีฟังก์ชันหรือค่าหลักเพียงอย่างเดียว
import default — import name from './file.js'
เมื่อ module มี `export default` — การ import จะใช้ syntax ที่ **ไม่มี `{ }`**: `import ชื่อที่ต้องการใช้ from './file.js';` สังเกตว่าไม่ต้องใส่ `{ }` รอบชื่อ — เพราะ default export มีค่าเดียว ไม่ต้องบอกว่าเอาตัวไหน
// math.js — export default แบบ function
export default function add(a, b) {
return a + b;
}
// main.js — import default
import calculateSum from './math.js';
console.log(calculateSum(5, 3)); // 8
// ========================================
// greeting.js — export default แบบ string
export default "สวัสดีครับ";
// main.js
import message from './greeting.js';
console.log(message); // "สวัสดีครับ"
// ========================================
// User.js — export default แบบ class
export default class User {
constructor(name) {
this.name = name;
}
}
// main.js
import UserClass from './User.js';
const user = new UserClass("Alice");
console.log(user.name); // "Alice"**ชื่อที่ import default สามารถตั้งได้อิสระ** — ไม่ต้องตรงกับชื่อที่ export: ```javascript // calculator.js export default function add(a, b) { return a + b; } // ทั้งหมดนี้ import แล้วใช้งานได้เหมือนกัน: import add from './calculator.js'; import sum from './calculator.js'; import calculate from './calculator.js'; import myMath from './calculator.js'; ``` เลือกชื่อที่สื่อความหมายกับการใช้งานในไฟล์นั้น — ไม่ต้องตรงกับชื่อฟังก์ชันต้นทาง
- **Import default** ไม่ต้องใช้ `{ }` — ใช้ `import name from './file.js'`
- **ชื่อที่ import** สามารถตั้งได้อิสระ — ไม่ต้องตรงกับชื่อที่ export
- Default export มักใช้เมื่อ module มีฟังก์ชันหรือค่าหลักเพียงอย่างเดียว
- ชื่อที่ import ควรอ่านง่ายและสื่อความหมายกับการใช้งาน
alias — import { original as newName }
Alias คือการ "ตั้งชื่อใหม่" ให้กับตัวที่ import ตอนนำเข้าจาก named export เพื่อ: - ป้องกันชื่อชนกับตัวแปรที่มีอยู่แล้ว - ทำให้ชื่ออ่านง่ายขึ้น - ทำให้โค้ดสื่อความหมายชัดเจนขึ้น
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export const PI = 3.14159;
// main.js — import พร้อม alias
import { add as sum, subtract as diff, PI as pi } from './math.js';
console.log(sum(5, 3)); // 8
console.log(diff(5, 3)); // 2
console.log(pi); // 3.14159**ทำไมต้องใช้ alias?** 1. **ป้องกันชื่อชน** — เมื่อ import ชื่อที่ไฟล์ปัจจุบันมีอยู่แล้ว: ```javascript // ไฟล์ปัจจุบันมีตัวแปร add อยู่แล้ว let add = 10; // ❌ จะ error — duplicate identifier import { add } from './math.js'; // ✅ ใช้ alias — ไม่ชนกัน import { add as mathAdd } from './math.js'; console.log(add); // 10 console.log(mathAdd(5, 3)); // 8 ``` 2. **ทำให้ชื่ออ่านง่ายขึ้น** — เมื่อชื่อ import ยาวหรือไม่สื่อ: ```javascript import { getUserById as fetchUser } from './api.js'; import { saveUserData as storeUser } from './db.js'; const user = fetchUser(123); storeUser(user); ```
- **Alias syntax**: `import { original as newName } from './file.js'`
- **`as`** — keyword สำหรับกำหนดชื่อใหม่ให้ตัวที่ import
- **Alias ช่วยป้องกันชื่อชน** กับตัวแปรที่มีอยู่แล้ว
- **Alias ทำให้ชื่ออ่านง่าย** และสื่อความหมายชัดเจนขึ้น
- ใช้ alias ได้กับ named import ได้เสมอ — และใช้ร่วมกับ default import ใน mixed import ได้
namespace — import * as nameSpace from './file.js'
**Namespace import** คือการ import ทุกอย่างจาก module เข้าไปใน object เดียว Syntax: `import * as nameSpace from './file.js';` ทุก named export จาก module นั้นจะกลายเป็น property ของ object `nameSpace` — เข้าถึงผ่าน dot notation
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
export const PI = 3.14159;
// main.js — namespace import
import * as math from './math.js';
// เข้าถึงผ่าน math object
console.log(math.add(5, 3)); // 8
console.log(math.subtract(10, 3)); // 7
console.log(math.multiply(4, 2)); // 8
console.log(math.PI); // 3.14159**เมื่อไหร่ควรใช้ namespace import?** - เมื่อต้องการ import เกือบทุกอย่างจาก module — ไม่อยากเขียนชื่อทีละตัวใน `{ }` - เมื่อต้องการจัดกลุ่มฟังก์ชันตาม module ต้นทาง — อ่านแล้วรู้ทันทีว่าฟังก์ชันนี้มาจาก module ไหน - เมื่อ module export จำนวนมากและใช้ import เกือบทั้งหมด ```javascript // import แยกแบบ named — ยาวและอ่านลำบาก import { add, subtract, multiply, divide, pow, sqrt, log, sin, cos, tan } from './math.js'; // namespace import — กระชับและจัดกลุ่มชัดเจน import * as math from './math.js'; console.log(math.add(5, 3)); console.log(math.sqrt(16)); ```
- **Namespace syntax**: `import * as nameSpace from './file.js'`
- **`*` (asterisk)** — import ทุก named export จาก module
- **`as`** — keyword สำหรับกำหนดชื่อ object ที่จะรวบรวมทุกอย่าง
- **Namespace object** — ทุก export จะอยู่ใต้ property ของ object นี้
- ใช้ namespace เมื่อต้องการ import หลายตัวและต้องการจัดกลุ่มตาม module ต้นทาง
mixed import — default + named พร้อมกัน
JavaScript อนุญาตให้ import default กับ named พร้อมกันในบรรทัดเดียว Syntax: `import defaultName, { named1, named2 } from './file.js';` หรือใช้ alias ร่วมกัน: `import defaultName, { named1 as alias1, named2 } from './file.js';`
// calculator.js
export default function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export const PI = 3.14159;
// main.js — mixed import (default + named)
import calculate, { subtract, PI } from './calculator.js';
console.log(calculate(5, 3)); // 8 (default)
console.log(subtract(10, 3)); // 7 (named)
console.log(PI); // 3.14159 (named)
// ========================================
// utils.js
export default function formatDate(date) {
return date.toLocaleDateString();
}
export function toUpper(str) {
return str.toUpperCase();
}
export function toLower(str) {
return str.toLowerCase();
}
// main.js — mixed import พร้อม alias
import formatDate, { toUpper as upper, toLower as lower } from './utils.js';
console.log(formatDate(new Date())); // "10/5/2569"
console.log(upper("hello")); // "HELLO"
console.log(lower("WORLD")); // "world"**รูปแบบที่ถูกต้องของ mixed import:** ```javascript // ✅ ถูกต้อง — default ก่อน แล้วตามด้วย named import defaultValue, { named1, named2 } from './file.js'; // ❌ ผิด — named ไม่สามารถอยู่ก่อน default import { named1, named2 }, defaultValue from './file.js'; // ✅ ถูกต้อง — default ก่อน แล้วตามด้วย named พร้อม alias import defaultValue, { named1 as alias1, named2 } from './file.js'; ``` **ข้อควรจำ:** 1. Default import อยู่ข้างหน้าเสมอ — ไม่ใส่ใน `{ }` 2. Named imports อยู่ใน `{ }` 3. สามารถใช้ alias กับ named imports ได้
- **Mixed syntax**: `import defaultName, { named1, named2 } from './file.js'`
- **Default import อยู่ข้างหน้าเสมอ** — ไม่ใส่ใน `{ }`
- **Named imports อยู่ใน `{ }`
- **สามารถใช้ alias** กับ named imports ใน mixed import
- **ห้ามสลับลำดับ** — named imports ไม่สามารถอยู่ก่อน default import
ข้อควรระวังและความเข้าใจผิดที่พบบ่อย
มือใหม่ที่เริ่มใช้ import ขั้นสูงมักเจอ error จากการสับสนระหว่าง default กับ named import — มาดูเรื่องที่พบบ่อยและวิธีแก้:
| เรื่องที่เข้าใจผิด / ทำผิด | สิ่งที่เกิดขึ้นจริง | วิธีแก้ |
|---|---|---|
| ใช้ `{ }` กับ default import | `SyntaxError` — default import ไม่ต้องใช้ `{ }` | ลบ `{ }` ออก — `import name from './file.js'` |
| ไม่ใช้ `{ }` กับ named import | `SyntaxError` — named import ต้องใช้ `{ }` | ใส่ `{ }` รอบชื่อ — `import { name } from './file.js'` |
| ลืม `as` สำหรับ alias | `SyntaxError` — keyword `as` หายไป | เพิ่ม `as` ก่อนชื่อใหม่ — `import { old as new } from './file.js'` |
| named import อยู่ก่อน default import | `SyntaxError` — default ต้องอยู่ก่อน | สลับลำดับ — `import default, { named } from './file.js'` |
| import default จาก module ที่ไม่มี default export | `SyntaxError` — module นั้นไม่มี default export | ตรวจสอบว่า module มี `export default` หรือเปล่า |
// ❌ ใช้ { } กับ default import
import { name } from './file.js'; // file.js มี export default
// ❌ SyntaxError: default export ไม่ต้องใช้ { }
// ✅ ถูกต้อง
import name from './file.js';
// ========================================
// ❌ ไม่ใช้ { } กับ named import
import name from './file.js'; // file.js มี export { name }
// ❌ SyntaxError: named export ต้องใช้ { }
// ✅ ถูกต้อง
import { name } from './file.js';
// ========================================
// ❌ ลืม as
import { original newName } from './file.js';
// ❌ SyntaxError: หา keyword as ไม่เจอ
// ✅ ถูกต้อง
import { original as newName } from './file.js';
// ========================================
// ❌ named อยู่ก่อน default
import { named }, default from './file.js';
// ❌ SyntaxError: default ต้องอยู่ก่อน
// ✅ ถูกต้อง
import default, { named } from './file.js';**Default import ตั้งชื่อได้อิสระ — ข้อควรระวัง:** เพราะ default import สามารถตั้งชื่อได้อิสระ ทำให้เกิดความสับสนได้ง่าย: ```javascript // calculator.js export default function add(a, b) { return a + b; } // main.js import subtract from './calculator.js'; // สับสน! ชื่อไม่ตรงกับ function จริงแต่โค้ดยังทำงาน console.log(subtract(5, 3)); // 8 — แต่ความหมายจริงคือ add ``` ทางปลอดภัย: - ตั้งชื่อให้สื่อความหมายกับสิ่งที่ import จริง ๆ - อ่าน source ของ module ก่อนถ้าไม่แน่ใจว่า export default คืออะไร
สรุป — import ขั้นสูง
- **Default import** — `import name from './file.js'` — ไม่มี `{ }` ใช้กับ default export
- **Named import** — `import { name } from './file.js'` — มี `{ }` ใช้กับ named export
- **Alias** — `import { original as newName }` — ตั้งชื่อใหม่ให้ตัวที่ import
- **Namespace** — `import * as ns from './file.js'` — import ทุกอย่างเข้า object
- **Mixed import** — `import default, { named } from './file.js'` — default ก่อน named หลัง
- **Default vs Named** — default มีได้ 1 ค่า (import ไม่มี `{ }`) named มีได้หลายค่า (import มี `{ }`)
| สิ่งที่อยากรู้ | คำตอบสั้น |
|---|---|
| default import syntax | `import name from './file.js'` — ไม่มี `{ }` |
| named import syntax | `import { name } from './file.js'` — มี `{ }` |
| alias syntax | `import { old as new } from './file.js'` |
| namespace syntax | `import * as ns from './file.js'` |
| mixed import syntax | `import default, { named } from './file.js'` |
ลองทำ — ใช้ default, alias, namespace
ถึงเวลาลองใช้ import ขั้นสูงด้วยตัวเองแล้ว! เราจะสร้าง project เล็ก ๆ ประกอบด้วย **3 ไฟล์**: 1. **`utils.js`** — module ที่ export default และ named exports ผสมกัน 2. **`main.js`** — ไฟล์หลักที่ import ทุกแบบจาก `utils.js` 3. **`index.html`** — หน้าเว็บที่โหลด `main.js` ผ่าน `<script type="module">` เปิด editor ของคุณ สร้าง folder ใหม่ (ตั้งชื่ออะไรก็ได้ เช่น `my-advanced-import`) แล้วสร้างไฟล์ตามด้านล่าง
// utils.js — module ที่มี default export และ named exports
// default export: function หลักที่ใช้บ่อยที่สุด
export default function greet(name) {
return "สวัสดี " + name + "!";
}
// named exports: utility functions อื่น ๆ
export function toUpper(str) {
return str.toUpperCase();
}
export function toLower(str) {
return str.toLowerCase();
}
export function repeat(str, count) {
return str.repeat(count);
}
export const PI = 3.14159;
export const E = 2.71828;// main.js — import ทุกแบบจาก utils.js
// 1. import default (ไม่มี { })
import greet from './utils.js';
// 2. import named พร้อม alias
import { toUpper as upper, toLower as lower } from './utils.js';
// 3. import named ปกติ
import { repeat } from './utils.js';
// 4. namespace import ทุกอย่าง
import * as utils from './utils.js';
// ลองใช้ทุกวิธี
console.log("--- Default Import ---");
console.log(greet("Alice"));
console.log("\n--- Named Import with Alias ---");
console.log(upper("hello world"));
console.log(lower("HELLO WORLD"));
console.log("\n--- Named Import ---");
console.log(repeat("ha", 3));
console.log("\n--- Namespace Import ---");
console.log(utils.PI);
console.log(utils.E);
console.log(utils.toUpper("namespace test"));<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>Advanced Import Demo</title>
</head>
<body>
<h1>เปิด Console (F12) เพื่อดูผลลัพธ์</h1>
<script type="module" src="main.js"></script>
</body>
</html>ไฟล์ทั้ง 3 ต้องอยู่ใน **folder เดียวกัน** โครงสร้างจะเป็นแบบนี้: ``` my-advanced-import/ ├── utils.js ├── main.js └── index.html ``` **วิธีรัน**: คลิกขวาที่ `index.html` ใน VS Code → เลือก **"Open with Live Server"** เบราว์เซอร์จะเปิดแท็บใหม่ จากนั้นกด **F12** เพื่อเปิด Console ⚠️ ห้ามเปิดไฟล์ HTML ตรง ๆ จาก file explorer — ต้องรันผ่าน **Live Server** เท่านั้น (URL ต้องเป็น `http://127.0.0.1:...`)
--- Default Import ---
สวัสดี Alice!
--- Named Import with Alias ---
HELLO WORLD
hello world
--- Named Import ---
hahaha
--- Namespace Import ---
3.14159
2.71828
NAMESPACE TEST- ถ้า console **ไม่แสดงอะไรเลย** → เช็คว่า `index.html` มี `type="module"` ใน `<script>` หรือยัง
- ถ้า console **แสดง error** → อ่านข้อความ error ดู — ส่วนใหญ่เกิดจาก path ผิด (ลืม `./` หรือลืม `.js`)
- ถ้า console **แสดง CORS error** → เปิดไฟล์ตรง ๆ ไม่ได้ผ่าน Live Server — ต้องใช้ Live Server
- ถ้าเห็นผลลัพธ์ครบตามด้านบน → **ผ่านแล้ว!** import ขั้นสูงทำงานถูกต้อง
เห็นผลลัพธ์ครบแล้ว? ลอง **ทดลองเปลี่ยนโค้ด** เพื่อทำความเข้าใจให้ลึกขึ้น: - ใน `main.js` ลอง **ใช้ { } กับ default import** — เปลี่ยน `import greet` เป็น `import { greet }` แล้ว refresh ดู error - ใน `main.js` ลอง **ลืม as** — เปลี่ยน `toUpper as upper` เป็น `toUpper upper` แล้วดู error - ใน `main.js` ลอง **สลับลำดับ** — เปลี่ยน `import greet, { upper }` เป็น `import { upper }, greet` แล้วดู error - ใน `main.js` ลอง **import namespace ผิด** — พยายามใช้ `utils.PI` แต่ไม่ import namespace แล้วดู error - เห็น error แล้วจำไว้ — พวกนี้คือ error ที่มือใหม่เจอบ่อยที่สุด รู้จักหน้าตาไว้จะช่วยแก้ไขได้เร็วขึ้น