JavaScript
Array Methods
forEach()
เรียนรู้ forEach() — method สำหรับวนผ่านทุก element เพื่อทำ side effect โดยไม่สร้าง array ใหม่ พร้อมเปรียบเทียบกับ for...of ผ่าน Lab 8 ข้อ
`forEach()` คืออะไร และคืนค่าอะไร
`forEach()` เป็น method ของ array ที่ใช้ **วนผ่านทุก element ทีละตัว** แล้วเรียก callback function ที่เราส่งเข้าไป จุดสำคัญที่สุดคือ `forEach()` มีไว้เพื่อ **ทำอะไรบางอย่างกับแต่ละตัว** เช่น `console.log`, สร้างข้อความ, สะสมผลลงตัวแปร, หรืออัปเดตค่าบางอย่าง `forEach()` **ไม่ได้สร้าง array ใหม่** และ **ค่าที่ return จาก callback จะไม่ถูกรวบเป็นผลลัพธ์ใหม่**
ตัวอย่างแรกตั้งใจให้เห็นก่อนว่า forEach() วนผ่านทุกตัว แล้วให้ callback ทำงานกับแต่ละตัว
const fruits = ["apple", "banana", "orange"];
fruits.forEach(function (fruit) {
console.log("ผลไม้:", fruit);
});
// output:
// ผลไม้: apple
// ผลไม้: banana
// ผลไม้: orangeถ้าคุณถามว่า `forEach()` คืนอะไร คำตอบคือ **คืน `undefined`** เพราะมันออกแบบมาเพื่อทำ side effect เท่านั้น — ไม่ได้สร้างค่าผลลัพธ์ใหม่ เช่น แสดงผล, เพิ่มข้อมูลลงตัวแปร, หรือเรียกคำสั่งอื่นในแต่ละรอบ
forEach() รับ array ต้นฉบับ แล้วส่ง element เข้า callback ทีละตัวเพื่อทำ side effect โดยไม่มี array ใหม่เป็นผลลัพธ์
callback parameters ของ `forEach()`
callback ของ `forEach()` รับ parameter ได้ 3 ตัวเหมือน array methods อื่น ๆ: • **element** — ค่า element ปัจจุบัน • **index** — ตำแหน่งของ element ปัจจุบัน • **array** — array ต้นฉบับทั้งหมด ส่วนใหญ่เราเริ่มจาก `element` ก่อน แล้วค่อยใช้ `index` เมื่ออยากแสดงลำดับหรืออ้างตำแหน่ง
const tasks = ["อ่านบทเรียน", "ทำ lab", "ทบทวน"];
tasks.forEach(function (task, index, arr) {
console.log("task:", task);
console.log("index:", index);
console.log("array:", arr);
});
// ส่วนใหญ่เราใช้แค่ element หรือ element + indexconst menu = ["ชาไทย", "โกโก้", "กาแฟ"];
menu.forEach(function (item, index) {
console.log((index + 1) + ". " + item);
});
// output:
// 1. ชาไทย
// 2. โกโก้
// 3. กาแฟสังเกตว่า callback จะถูกเรียกให้ทุกตัวใน array ตามลำดับจากซ้ายไปขวา เราไม่ต้องจัดการ index เองเหมือน `for` loop
ใช้ `forEach()` เมื่อไหร่
ใช้ `forEach()` เมื่อโจทย์คือ **"ทำอะไรกับทุก element"** แต่ **ไม่ได้ต้องการ array ใหม่** ตัวอย่างงานที่เหมาะ: • log ข้อมูลทุกตัว • สร้างข้อความรายงานทีละบรรทัด • รวมข้อความลงตัวแปร • เรียก function บางอย่างกับทุกตัว
ตัวอย่างนี้ใช้ side effect โดยต่อข้อความลงตัวแปร report ทีละรอบ
const scores = [82, 91, 76];
let report = "";
scores.forEach(function (score, index) {
report += "คนที่ " + (index + 1) + ": " + score + " คะแนน\n";
});
console.log(report);
// คนที่ 1: 82 คะแนน
// คนที่ 2: 91 คะแนน
// คนที่ 3: 76 คะแนน- `forEach()` เหมาะกับงานแบบ side effect
- ถ้าต้องการ array ใหม่ — ใช้ `for...of` + `push` เอง
- ถ้าต้องการควบคุม loop มากขึ้น เช่น `break` หรือ `continue` ให้ใช้ `for` หรือ `for...of`
`forEach()` vs `for...of`
ทั้ง `forEach()` และ `for...of` ใช้วนผ่านข้อมูลได้ แต่ **เจตนา** ต่างกัน: • **`forEach()`** — อยากทำอะไรกับทุกตัว โดยให้ callback จัดการทีละ element ไม่ต้องเขียนเงื่อนไข loop เอง • **`for...of`** — อยากวน loop แบบยืดหยุ่น ควบคุมแต่ละรอบเองได้ เช่น `break` ออกกลางทาง หรือ `continue` ข้ามบางค่า
| โจทย์ | `forEach()` | `for...of` |
|---|---|---|
| แสดงผลทุกตัว | เหมาะ — สั้น อ่านง่าย | เหมาะ — แต่ต้องเขียน console.log เองทุกรอบ |
| แปลงข้อมูลทุกตัวแล้วสร้าง array ใหม่ | ทำได้ — ใช้ `push` ลง array ใหม่ | ทำได้ — ใช้ `push` ลง array ใหม่ |
| อยากหยุด loop ก่อน | ทำไม่ได้ — `forEach()` วนครบทุกตัวเสมอ | ทำได้ — `break` หยุด loop เมื่อต้องการ |
| อยากข้ามบางค่า | ทำไม่ได้ — `forEach()` วนทุกตัว | ทำได้ — `continue` ข้ามรอบที่ไม่ต้องการ |
forEach() สั้นกว่า อ่านง่ายกว่า — for...of ให้อิสระมากกว่า
const names = ["Ada", "Lin", "Mew"];
// ใช้ forEach() — callback จัดการให้ทีละตัว
names.forEach(function (name) {
console.log("Hello", name);
});
// ใช้ for...of — เราควบคุมแต่ละรอบเอง
for (const name of names) {
console.log("Hello", name);
}
// ทั้งสองแบบให้ผลลัพธ์เหมือนกันทุกประการconst numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// for...of — หยุดเมื่อเจอค่าที่มากกว่า 5
for (const n of numbers) {
if (n > 5) {
break;
}
console.log(n); // output: 1 2 3 4 5
}
// forEach() — เขียน break ไม่ได้ จะวนครบทุกตัวเสมอสรุปง่าย ๆ: ถ้าอยากทำอะไรกับทุกตัวแบบตรงไปตรงมา → `forEach()` ถ้าต้องควบคุม loop เช่น `break` หรือข้ามบางค่า → `for...of`
ข้อควรระวังเมื่อใช้ `forEach()`
| จุดที่พลาดบ่อย | ปัญหา | วิธีคิดที่ถูก |
|---|---|---|
| คิดว่า `forEach()` จะคืน array ใหม่ | เอาผลลัพธ์ไปเก็บแล้วได้ `undefined` | `forEach()` มีไว้ทำ side effect ไม่ใช่สร้าง array ใหม่ |
| ใส่ `return` ใน callback แล้วคิดว่าจะหยุด loop | loop ยังทำต่อทุกตัว | `return` แค่ออกจาก callback รอบนั้น ไม่ได้หยุด `forEach()` |
| อยากใช้ `break` ใน `forEach()` | เขียนไม่ได้ | ถ้าต้องหยุดกลางทาง ให้ใช้ `for` หรือ `for...of` |
const numbers = [1, 2, 3];
// ❌ ไม่เหมาะ — อยากได้ array ใหม่ แต่ใช้ forEach()
const doubled = numbers.forEach(function (n) {
return n * 2;
});
console.log(doubled); // undefined
// ✅ ถูก — ถ้าอยากได้ array ใหม่ ใช้ for...of + push
const result = [];
for (const n of numbers) {
result.push(n * 2);
}
console.log(result); // [2, 4, 6]สรุปสั้น ๆ: ถ้าโจทย์คือ **ทำอะไรกับทุกตัว** ให้คิดถึง `forEach()` ก่อน แต่ถ้าโจทย์คือ **สร้าง array ใหม่** พร้อมควบคุม loop ได้ ใช้ `for...of` + `push`