JavaScript
Array Methods
map
เรียนรู้ map() — method แปลงทุก element ใน array และคืน array ใหม่ขนาดเท่าเดิม โดยไม่เปลี่ยนต้นฉบับ ตั้งแต่ callback function, element กับ index parameter, การแปลงตัวเลขและข้อความ, ข้อผิดพลาดที่พบบ่อย ไปจนถึง map() vs for loop ผ่าน Lab 3 ข้อ
`map()` คืออะไร — แปลงทุก element และคืน array ใหม่
`map()` เป็น method ของ array ที่รับ callback function — เรียก callback ทุกตัวใน array จากนั้นคืน (return) array ใหม่ที่เกิดจากการ return ของ callback ในแต่ละรอบ กฎสำคัญ: • `map()` จะคืน array ใหม่เสมอ — ขนาดเท่าเดิม ไม่ว่า callback จะ return อะไร • `map()` ไม่เปลี่ยน array ต้นฉบับ (immutable method) • callback function ต้อง return ค่า — ถ้าไม่ return จะได้ `undefined` แทน ใช้ `map()` เมื่อคุณอยากสร้าง array ใหม่จากการแปลง (transform) ทุก element — เช่น แปลงราคาจากบาทเป็นดอลลาร์, แปลงชื่อจากพิมพ์เล็กเป็นพิมพ์ใหญ่, หรือดึงค่า property หนึ่งจากทุก object
const nums = [1, 2, 3, 4, 5];
// map() รับ arrow function และคืน array ใหม่ที่คูณ 2 ทุกตัว
const doubled = nums.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(nums); // [1, 2, 3, 4, 5] ← ต้นฉบับไม่เปลี่ยน ✓
สิ่งสำคัญที่ต้องรู้: • callback จะรับ element แต่ละตัว — ในตัวอย่างนี้ `n` คือ element (1, 2, 3, 4, 5) ตามลำดับ • callback ต้อง return ค่า — `n * 2` คือการ return ค่าแบบ shorthand ของ arrow function • `map()` จะเอา return value มารวมเป็น array ใหม่ให้ — `[2, 4, 6, 8, 10]`
map() รับ element แต่ละตัว → ส่งให้ callback → เก็บ return value → คืน array ใหม่ขนาดเท่าเดิม
Callback function ของ `map()` — element, index, array
callback function ที่ส่งให้ `map()` จะรับ parameter ได้ 3 ตัว: • **element** — ค่าของ element ปัจจุบัน (ใช้บ่อยที่สุด) • **index** — ตำแหน่ง index ของ element ปัจจุบัน • **array** — array ต้นฉบับทั้งหมด (ใช้น้อยมาก) ส่วนใหญ่เราใช้แค่ element ตัวแรกก็เพียงพอ แต่เมื่อต้องการใช้ตำแหน่งด้วย `index` ก็ช่วยได้มาก
const names = ["สมชาย", "สมหญิง", "สมศรี"];
// ใช้แค่ element — ตัวแปร n (ชื่อ)
const greetings = names.map(n => "สวัสดี " + n);
console.log(greetings);
// ['สวัสดี สมชาย', 'สวัสดี สมหญิง', 'สวัสดี สมศรี']
const fruits = ["แอปเปิ้ล", "กล้วย", "ส้ม"];
// ใช้ element กับ index — ตัวแปร f (ผลไม้), i (ลำดับ)
const label = fruits.map((f, i) => (i + 1) + ". " + f);
console.log(label);
// ['1. แอปเปิ้ล', '2. กล้วย', '3. ส้ม']
วิธีเขียน callback — เลือกสไตล์ที่เหมาะกับสถานการณ์: • **Arrow function แบบ shorthand** — `n => n * 2` — สั้น ใช้มากที่สุด สำหรับการ return แบบง่าย • **Arrow function แบบเต็ม** — `(n) => { return n * 2; }` — ใช้เมื่อมี logic หลายบรรทัด • **Function expression** — `function(n) { return n * 2; }` — ใช้เมื่อต้องการชื่อหรือมี `this` สำหรับบทนี้เราจะใช้ arrow function shorthand เป็นหลัก เพราะสั้นและอ่านง่ายที่สุด
`map()` ในสถานการณ์จริง
`map()` เจอบ่อยมากในงานจริง — การแปลงข้อมูลเป็นงานที่ทำทุกวัน เช่น: • แปลง array ของตัวเลข (ราคา, อุณหภูมิ, คะแนน) • ดึง property หนึ่งออกจาก array ของ object • สร้าง HTML หรือข้อความจากข้อมูล • แปลงรูปแบบข้อมูลก่อนส่งไป API • เวลาอยากได้เฉพาะแค่ค่าบางอย่างจากข้อมูลทั้งหมด
const prices = [100, 250, 80, 500];
// ลดราคา 20% ทุกรายการ
const discounted = prices.map(p => p * 0.8);
console.log(discounted); // [80, 200, 64, 400]
// เพิ่ม VAT 7%
const withVat = prices.map(p => p * 1.07);
console.log(withVat); // [107, 267.5, 85.6, 535]
const students = [
{ name: "สมชาย", score: 85 },
{ name: "สมหญิง", score: 62 },
{ name: "สมศรี", score: 91 },
];
// ดึงเฉพาะชื่อ
const studentNames = students.map(s => s.name);
console.log(studentNames); // ['สมชาย', 'สมหญิง', 'สมศรี']
// ดึงเฉพาะคะแนน
const scores = students.map(s => s.score);
console.log(scores); // [85, 62, 91]
// สร้างข้อความสรุป
const summary = students.map(s => s.name + " ได้ " + s.score + " คะแนน");
console.log(summary);
// ['สมชาย ได้ 85 คะแนน', 'สมหญิง ได้ 62 คะแนน', 'สมศรี ได้ 91 คะแนน']
ข้อผิดพลาดที่พบบ่อยเมื่อใช้ `map()`
- ลืม `return` ใน callback — `map(n => { n * 2 })` ได้ array ของ `undefined` — เพราะ `{ }` ใน arrow function ต้องมี `return` ชัดเจน — แก้โดยใช้ shorthand `n => n * 2` หรือเติม `return`
- คิดว่า `map()` เปลี่ยน array ต้นฉบับ — `map()` จะไม่เปลี่ยนต้นฉบับ — ต้องเก็บผลลัพธ์ในตัวแปรใหม่เสมอ — `const newArr = oldArr.map(...)`
- ใช้ `map()` เมื่อไม่ต้องการ return ค่าใหม่ — ถ้าต้องการแค่ loop โดยไม่เปลี่ยนค่า ควรใช้ `forEach()` หรือ `for...of` — `map()` มีไว้เพื่อ "แปลง" ไม่ใช่ "ทำอะไรสักอย่าง"
- ลืมเก็บผลลัพธ์ของ `map()` — `arr.map(...)` เฉย ๆ โดยไม่มีตัวแปร — ผลลัพธ์จะหายไป — ต้องเก็บผลลัพธ์เสมอ: `const result = arr.map(...)`
const nums = [1, 2, 3];
// ❌ ผิด — ลืม return (arrow function ใช้ { } )
const wrong = nums.map(n => {
n * 2; // ← ไม่มี return!
});
console.log(wrong); // [undefined, undefined, undefined]
// ✅ ถูก — ใช้ shorthand (ไม่มี { })
const correct1 = nums.map(n => n * 2);
// ✅ ถูก — ใช้ return ชัดเจน
const correct2 = nums.map(n => {
return n * 2;
});
console.log(correct1); // [2, 4, 6]
console.log(correct2); // [2, 4, 6]
const names = ["สมชาย", "สมหญิง"];
// ❌ ใช้ map() แต่ไม่ต้องการแปลงค่า — แค่ console.log
names.map(n => console.log(n));
// ได้ array [undefined, undefined] ที่ไม่ใช้ — เปลือง
// ✅ ใช้ forEach() — สำหรับทำอะไรโดยไม่ต้อง return
names.forEach(n => console.log(n));
// ✅ ใช้ map() เมื่อต้องการแปลงค่าจริง ๆ
const greetings = names.map(n => "สวัสดี " + n);
console.log(greetings); // ['สวัสดี สมชาย', 'สวัสดี สมหญิง']
`map()` vs `for` loop — เลือกใช้ให้เหมาะ
ทั้ง `map()` และ `for` loop ใช้แปลง array ได้ — แต่แนวคิดต่างกัน: • `map()` — บอก **ผลลัพธ์** ที่อยากได้ (declarative — "ฉันอยากได้ array ใหม่ที่เป็น 2 เท่า") • `for` loop — บอก **ขั้นตอน** ทีละขั้น (imperative — "เริ่มที่ index 0, เอา element มา, คูณ 2, ใส่ array ใหม่, เพิ่ม index...") `map()` สั้นกว่า อ่านง่ายกว่า และไม่ต้องจัดการ index เอง
| เรื่อง | map() | for loop |
|---|---|---|
| จำนวนบรรทัด | 1–2 บรรทัด | 4–5 บรรทัด |
| ต้องจัดการ index | ไม่ต้อง (เว้นแต่ใช้ index) | ต้องจัดการเอง |
| ต้องสร้าง array เปล่า | ไม่ต้อง — map คืน array ให้เลย | ต้องสร้างเอง + push เอง |
| เปลี่ยนต้นฉบับไหม | ไม่เปลี่ยน ✓ | ไม่เปลี่ยน (ถ้าใช้ array ใหม่) |
| อ่านโค้ดรู้เรื่องไหม | อ่านแล้วเข้าใจเจตนาทันที | ต้องไล่อ่านจึงรู้ว่าทำอะไร |
| เมื่อไหร่ควรใช้ | เมื่อต้องการแปลงทุก element | เมื่อต้องการเงื่อนไขซับซ้อน หรือ skip บาง element |
const nums = [1, 2, 3, 4, 5];
// === ใช้ map() — 1 บรรทัด
const doubled1 = nums.map(n => n * 2);
// === ใช้ for loop — 5 บรรทัด
const doubled2 = [];
for (let i = 0; i < nums.length; i++) {
doubled2.push(nums[i] * 2);
}
console.log(doubled1); // [2, 4, 6, 8, 10]
console.log(doubled2); // [2, 4, 6, 8, 10]
เคล็ดลับ: ถ้าโจทย์คือ "แปลงทุก element ให้เป็นค่าใหม่" → ใช้ `map()` — ถ้าโจทย์คือ "ทำอะไรบางอย่างกับทุก element แต่ไม่ต้องการ array ใหม่" → ใช้ `forEach()` หรือ `for...of` — ถ้าโจทย์คือ "วน loop แบบมีเงื่อนไขซับซ้อน" → ใช้ `for` loop