JavaScript
Import / Export
CommonJS module.exports
เรียนรู้ CommonJS module.exports — การ export ค่าในระบบ module ของ Node.js
CommonJS export คืออะไร — module.exports
ในบท import-common เราเรียนวิธี `require()` — import ค่าจาก module อื่นมาใช้ แต่เราไม่ได้เรียนว่าค่าเหล่านั้นถูกสร้างและ export ขึ้นมายังไง บทนี้เราจะเรียนฝั่งตรงข้าม — วิธี **export** ในระบบ CommonJS: - **`module.exports`** — object ที่บอกว่า module นี้มีอะไรให้ require ได้บ้าง - **`exports`** — shortcut ไปยัง `module.exports` CommonJS export ใช้ใน **Node.js** เท่านั้น — เหมือน `require()` — ไม่ใช้ใน browser
// math.js
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
const PI = 3.14159;
// module.exports — object ที่บอกว่าไฟล์อื่น require อะไรได้บ้าง
module.exports = { add, multiply, PI };
// main.js — require เข้ามาใช้
const { add, multiply, PI } = require('./math.js');
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
console.log(PI); // 3.14159**`module.exports` ใน Node.js:** - เริ่มต้น `module.exports` เป็น empty object `{}` - เรา assign ค่าให้มัน — `module.exports = { add, PI };` - `require()` จะ return ค่า `module.exports` — ไม่ว่ามันจะเป็น object, function, string, หรืออะไรก็ตาม นี่คือหลักการของ CommonJS: **สิ่งที่ module export = ค่าที่ assign ให้ `module.exports`**
- **`module.exports`** — object พิเศษของ Node.js ที่กำหนดว่า module นี้ export อะไร
- **`require()` return `module.exports`** — import ได้ค่าตรงนี้
- **export ได้หลายค่า** — ใส่ทุกอย่างใน object แล้ว assign ให้ `module.exports`
- **export ได้ทุกรูปแบบ** — function, object, string, number, array — ใส่ใน `module.exports` ได้หมด
module.exports = { } — export หลายค่า
วิธี export หลายค่าใน CommonJS: 1. ประกาศฟังก์ชัน / ตัวแปรก่อน 2. รวมทุกอย่างใน object 3. assign ให้ `module.exports`
// utils.js
function toUpperCase(text) {
return text.toUpperCase();
}
function toLowerCase(text) {
return text.toLowerCase();
}
const PI = 3.14159;
const E = 2.71828;
module.exports = {
toUpperCase,
toLowerCase,
PI,
E
};
// main.js — require ทั้ง module
const utils = require('./utils.js');
console.log(utils.toUpperCase("hello")); // "HELLO"
console.log(utils.PI); // 3.14159
// หรือ destructuring
const { toLowerCase, E } = require('./utils.js');
console.log(toLowerCase("WORLD")); // "world"
console.log(E); // 2.71828// greet.js — export function โดยตรง
function greet(name) {
return "สวัสดี " + name;
}
module.exports = greet;
// main.js
const greet = require('./greet.js');
console.log(greet("Alice")); // "สวัสดี Alice"
// config.js — export string โดยตรง
const API_URL = "https://api.example.com";
module.exports = API_URL;
// main.js
const apiUrl = require('./config.js');
console.log(apiUrl); // "https://api.example.com"- `module.exports = { key1, key2 }` — export หลายค่าใน object
- `module.exports = functionName` — export function โดยตรง
- `module.exports = value` — export ค่าเดียวโดยตรง (string, number, etc.)
- key ที่ export ต้องตรงกับชื่อตอน `require` — case-sensitive
exports.name = ... — shortcut ในการ export ทีละตัว
นอกจาก `module.exports = { }` แล้ว — CommonJS ยังมี shortcut: `exports.name = ...` แทนที่จะรวมทุกอย่างไว้ท้ายไฟล์: ```javascript module.exports = { add, subtract, multiply, PI }; ``` ใช้ `exports.add = function() { ... }` ทีละตัวก็ได้: ```javascript exports.add = function(a, b) { ... }; exports.PI = 3.14159; ``` **ข้อควรรู้:** `exports` คือ reference ไปยัง `module.exports` — ถ้าไม่ reassign `module.exports` โดยตรง มันก็จะทำงานได้เหมือนกัน
// math.js — ใช้ exports ทีละตัว
exports.add = function(a, b) {
return a + b;
};
exports.subtract = function(a, b) {
return a - b;
};
exports.multiply = function(a, b) {
return a * b;
};
exports.PI = 3.14159;
// main.js — require ใช้ได้เหมือนเดิม
const math = require('./math.js');
console.log(math.add(5, 3)); // 8
console.log(math.subtract(10, 3)); // 7
console.log(math.PI); // 3.14159- `exports.name = value` — shortcut เพิ่มทีละ key ให้ `module.exports`
- `exports` ใช้ได้เฉพาะเพิ่ม property — ห้าม reassign `exports` โดยตรง
- ใช้ `exports` เมื่อต้องการ export หลายตัวแบบกระจาย — ไม่ต้องรวบไว้ท้ายไฟล์
- ใช้ `module.exports = { }` เมื่อต้องการ export รวบไว้ที่เดียว — อ่านง่ายกว่า
module.exports vs exports — ข้อควรระวัง reference cut
**นี่คือ bug ที่มือใหม่เจอบ่อยที่สุดใน CommonJS** — การ reassign `exports` จะตัด reference ไปยัง `module.exports` ทำให้ export ไม่ทำงาน `exports` เริ่มต้นเป็น reference ไปยัง `module.exports` (ทั้งคู่ชี้ไปที่ object เดียวกัน) ถ้าคุณ reassign `exports = { ... }` — มันจะสร้าง object ใหม่ให้ `exports` แต่ `module.exports` ยังชี้ไปที่ object เดิม → `require()` จะได้ object เปล่า!
// ❌ ผิด — reassign exports = object ใหม่
// math.js
exports = {
add: function(a, b) { return a + b; },
PI: 3.14159
};
// main.js
const math = require('./math.js');
console.log(math); // {} — object เปล่า! exports ใหม่ไม่ถึง module.exports
// ========================================
// ✅ ถูกต้อง — ใช้ module.exports โดยตรง
// math.js
module.exports = {
add: function(a, b) { return a + b; },
PI: 3.14159
};
// main.js
console.log(math.add(5, 3)); // 8 ✅
// ========================================
// ✅ ถูกต้อง — ใช้ exports.property (เพิ่มทีละ key ไม่ reassign)
// math.js
exports.add = function(a, b) { return a + b; };
exports.PI = 3.14159;
// main.js
console.log(math.add(5, 3)); // 8 ✅- ⚠️ **ห้าม reassign `exports` โดยตรง** — `exports = { }` จะตัด reference ไป `module.exports`
- ✅ ใช้ `exports.name = ...` (เพิ่ม property ทีละตัว) — ใช้ได้
- ✅ ใช้ `module.exports = { }` — ปลอดภัยที่สุด
- **จำง่าย ๆ:** `module.exports` ใช้กับ `{ }` ได้, `exports` ใช้เฉพาะ dot notation
ข้อควรระวังและความเข้าใจผิดที่พบบ่อย
มือใหม่ที่เริ่มใช้ CommonJS export มักเจอ error จากการใช้ `exports` ผิดหรือสับสนกับ ES module — มาดูเรื่องที่พบบ่อยและวิธีแก้:
| เรื่องที่เข้าใจผิด / ทำผิด | สิ่งที่เกิดขึ้นจริง | วิธีแก้ |
|---|---|---|
| `exports = { add, PI }` — reassign exports | `require()` ได้ object เปล่า `{}` — ไม่ error ที่ compile time | ใช้ `module.exports = { add, PI }` แทน |
| ใช้ `export` แทน `module.exports` (นึกว่าเป็น ES module) | โค้ดทำงานใน Node.js? ใน Node.js: ไม่ error ถ้าไม่ได้ตั้ง `"type": "module"` — แต่ export ไม่มีความหมาย | CommonJS ใช้ `module.exports` — ES Module ใช้ `export` — ห้ามสับสน |
| require ผิด key — case ไม่ตรง | `require()` ได้ `undefined` — ไม่ error | ตรวจสอบ key ใน `module.exports` — ตัวเล็กตัวใหญ่ต้องตรงกัน |
| ลืม export — function อยู่ข้างใน module แต่ไม่ถูก add ใน module.exports | `require()` แล้วใช้ไม่ได้ — ได้ `undefined` | เพิ่ม key ใน `module.exports` เสมอ — `module.exports = { name };` |
| รัน CommonJS ใน browser | `ReferenceError: require is not defined` | CommonJS ใช้ใน Node.js เท่านั้น — ใช้ `node` รัน |
// ❌ exports = { } — reference cut
exports = {
add: function(a, b) { return a + b; }
};
// require() จะได้ {} — exports ใหม่ไม่ถึง module.exports
// ❌ ลืม add ลง module.exports
function add(a, b) {
return a + b;
}
const PI = 3.14159;
// function add กับ PI ใช้ไม่ได้จากไฟล์อื่น — ไม่ได้ export!
// ❌ ใช้ export แทน module.exports
// (เข้าใจผิดว่าเป็น ES module)
export function add(a, b) { return a + b; }
// ใน CommonJS file — อาจไม่ error แต่ export ไม่ทำงานตามที่คิด
// ✅ ถูกต้อง — module.exports
const add = (a, b) => a + b;
const PI = 3.14159;
module.exports = { add, PI };สรุป — CommonJS module.exports
- **`module.exports = { }`** — export หลายค่าใน object — ใช้ใน Node.js เท่านั้น
- **`module.exports = fn`** — export function หรือค่าเดียวโดยตรง
- **`exports.name = value`** — shortcut เพิ่มทีละ key — ห้าม reassign `exports`
- **⚠️ `exports = { }` — reference cut** — require() จะได้ object เปล่า
- **CommonJS ใช้ใน browser ไม่ได้** — ต้องใช้ Node.js รันด้วย `node`
- **export vs module.exports** — คนละระบบ — CommonJS ใช้ `module.exports`, ES Module ใช้ `export`
| สิ่งที่อยากรู้ | คำตอบสั้น |
|---|---|
| export หลายค่า | `module.exports = { a, b, c }` |
| export function เดียว | `module.exports = myFunction` |
| exports shortcut | `exports.name = value` (เพิ่มทีละตัว) |
| exports reassign | ⚠️ ห้ามทำ — `exports = { }` จะตัด reference |
| import ยังไง | `const { x } = require('./file.js')` — เรียนบท import-common |
ลองทำ — ใช้ module.exports ใน Node.js
ถึงเวลาลองใช้ `module.exports` ด้วยตัวเองแล้ว! เราจะสร้าง project เล็ก ๆ ประกอบด้วย **2 ไฟล์**: 1. **`math.js`** — module ที่ export ฟังก์ชันคำนวณและค่าคงที่ 2. **`main.js`** — ไฟล์หลักที่ require และใช้งาน เปิด editor ของคุณ สร้าง folder ใหม่ (ตั้งชื่ออะไรก็ได้ เช่น `my-commonjs-export`) แล้วสร้างไฟล์ตามด้านล่าง
// math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
return a / b;
}
const PI = 3.14159;
const E = 2.71828;
module.exports = {
add,
subtract,
multiply,
divide,
PI,
E
};// main.js
// แบบที่ 1: require ทั้ง module
const math = require('./math.js');
console.log("=== require ทั้ง module ===");
console.log("PI =", math.PI);
console.log("E =", math.E);
console.log("5 + 3 =", math.add(5, 3));
console.log("10 - 5 =", math.subtract(10, 5));
console.log("7 × 6 =", math.multiply(7, 6));
console.log("20 ÷ 4 =", math.divide(20, 4));
// แบบที่ 2: destructuring
console.log("\n=== destructuring ===");
const { add, multiply, PI } = require('./math.js');
console.log("10 + 20 =", add(10, 20));
console.log("PI × 2 =", multiply(PI, 2));ไฟล์ทั้ง 2 ต้องอยู่ใน **folder เดียวกัน** โครงสร้างจะเป็นแบบนี้: ``` my-commonjs-export/ ├── math.js └── main.js ``` **วิธีรัน**: เปิด terminal → cd เข้า folder → รัน: ```bash node main.js ``` ⚠️ CommonJS ใช้ใน browser ไม่ได้ — ต้องใช้ Node.js รันใน terminal
=== require ทั้ง module ===
PI = 3.14159
E = 2.71828
5 + 3 = 8
10 - 5 = 5
7 × 6 = 42
20 ÷ 4 = 5
=== destructuring ===
10 + 20 = 30
PI × 2 = 6.28318- ถ้า terminal **Error: Cannot find module** → ตรวจสอบ path — ต้องมี `./` นำหน้า ชื่อไฟล์ต้องตรงกัน
- ถ้า terminal **ได้ค่าที่ไม่คาดคิด** → ตรวจสอบ key ใน `module.exports` — ตัวเล็กตัวใหญ่ต้องตรงกัน
- ถ้า terminal **ได้ undefined** → เช็คว่าลืมใส่ key ใน `module.exports` หรือเปล่า
- ถ้าเห็นผลลัพธ์ครบตามด้านบน → **ผ่านแล้ว!** module.exports ทำงานถูกต้อง
เห็นผลลัพธ์ครบแล้ว? ลอง **ทดลองเปลี่ยนโค้ด** เพื่อทำความเข้าใจให้ลึกขึ้น: - ใน `math.js` ลอง **เปลี่ยนจาก `module.exports` เป็น `exports` ทีละตัว** — ใช้ `exports.add = add; exports.PI = PI;` แทน `module.exports = { }` แล้วรันใหม่ - ใน `math.js` ลอง **ทำให้ bug reference cut** — เปลี่ยนเป็น `exports = { add, PI }` (อย่าเป็น `exports.`) แล้วรันดูว่า `main.js` ได้ object เปล่า - ใน `math.js` ลอง **export function โดยตรง** — เปลี่ยนเป็น `module.exports = add;` แล้วใน `main.js` require และเรียกใช้เป็น function - เห็นความแตกต่างระหว่าง `module.exports` กับ `exports` แล้วจำไว้ — bug นี้มือใหม่เจอบ่อยที่สุด