JavaScript
Loop Arrays & Objects
for loop กับ array (เมื่อจำเป็นต้องใช้ index)
เรียนรู้ว่าเมื่อโจทย์ต้องใช้ `index`, `arr[i]`, `arr.length`, การดู element ข้างเคียง, การกัน off-by-one และการแก้ค่าใน array โดยตรง `for` loop ยังเป็นเครื่องมือที่เหมาะที่สุด
ทำไมบทนี้ยังจำเป็นแม้มี `for...of` แล้ว
`for...of` เหมาะมากเมื่อคุณต้องการแค่ค่า element แต่ `for` loop ยังจำเป็นเมื่อโจทย์ต้องใช้ **ตำแหน่งของข้อมูล** เช่น ลำดับข้อ, element ก่อนหน้า/ถัดไป, หรือการแก้ค่าใน array ช่องเดิม ให้จำง่าย ๆ ว่า `for...of` คือ value-first ส่วนบทนี้คือ index-first
| โจทย์ | `for` กับ array | `for...of` |
|---|---|---|
| อยากได้ค่า element ทีละตัว | ทำได้ แต่ยาวกว่า | ✓ เหมาะกว่า |
| อยากได้ index | ✓ มี `i` ให้ใช้ | ✗ ไม่มีให้ตรง ๆ |
| อยากดู element ข้างเคียง | ✓ ใช้ `arr[i - 1]`, `arr[i + 1]` | ✗ ไม่ตรงโจทย์ |
| อยากแก้ค่ากลับเข้า array ช่องเดิม | ✓ `arr[i] = ...` | ✗ ไม่เหมาะ |
ตัวอย่างนี้คือเหตุผลที่ `for` ยังมีบทของตัวเอง เพราะเราต้องใช้ทั้งตำแหน่งและค่าในรอบเดียว
const fruits = ["apple", "banana", "cherry"];
// ใช้เมื่ออยากได้ทั้ง index และ value
for (let i = 0; i < fruits.length; i++) {
console.log((i + 1) + ". " + fruits[i]);
}
// "1. apple"
// "2. banana"
// "3. cherry"`i` คือจุดเด่นของบทนี้ เพราะมันบอกได้ทั้งตำแหน่งปัจจุบันและเปิดทางให้เข้าถึง `arr[i]`
`for` กับ array ให้ทั้ง index และ value ผ่าน `arr[i]`
ในแต่ละรอบ `for` จะให้ `i` ซึ่งเป็น index ปัจจุบัน แล้วเราค่อยใช้ `arr[i]` เพื่อดึงค่าของช่องนั้นออกมา ข้อดีคือเราไม่ได้แค่ “ได้ค่า” แต่ยังรู้ด้วยว่าค่านั้นอยู่ตำแหน่งไหน
นี่คือ mental model หลักของบทนี้: `i` บอกตำแหน่ง ส่วน `scores[i]` คือค่าที่ตำแหน่งนั้น
const scores = [88, 75, 92, 61];
for (let i = 0; i < scores.length; i++) {
console.log("index:", i, "value:", scores[i]);
}
// index: 0 value: 88
// index: 1 value: 75
// index: 2 value: 92
// index: 3 value: 61เมื่อมี `i` แล้ว เราจึงทำโจทย์ที่อิงตำแหน่งได้ง่าย เช่น แสดงลำดับข้อ, ข้ามบางช่อง, หรือเทียบข้อมูลกับ element ก่อนหน้าและถัดไป
ใช้ `for` เมื่อโจทย์ต้องอ้างตำแหน่งหรือ element ข้างเคียง
ถ้าโจทย์ต้องรู้ว่า “ตัวนี้อยู่ลำดับที่เท่าไหร่” หรือ “ตัวก่อนหน้าคืออะไร” `for` จะเหมาะกว่า เพราะเราเข้าถึงตำแหน่งปัจจุบันและขยับไปดูช่องใกล้เคียงได้จาก `i`
ตัวอย่างนี้ต้องดู `temperatures[i]` เทียบกับ `temperatures[i - 1]` ซึ่งเป็นโจทย์แบบ index-first ชัดเจน
const temperatures = [30, 31, 31, 29, 32];
for (let i = 1; i < temperatures.length; i++) {
if (temperatures[i] === temperatures[i - 1]) {
console.log("ซ้ำกันที่ index", i - 1, "และ", i);
}
}
// "ซ้ำกันที่ index 1 และ 2"- แสดงลำดับข้อแบบ `1. item`, `2. item`
- ดูค่าก่อนหน้าด้วย `arr[i - 1]`
- ดูค่าถัดไปด้วย `arr[i + 1]` เมื่อเช็กขอบเขตแล้ว
- ข้ามบางตำแหน่งหรือเริ่มลูปจาก index เฉพาะจุด
ใช้ `arr.length` และหลีกเลี่ยง off-by-one
เมื่อใช้ `for` กับ array เราต้องดูแลเงื่อนไขหยุดเองเสมอ จึงควรใช้ `i < arr.length` เป็นค่า default และหลีกเลี่ยงการ hard-code จำนวนตายตัว
`arr.length` ช่วยให้ลูปสัมพันธ์กับขนาดจริงของข้อมูล และลดโอกาสเกิด `undefined` จากการวนเกิน
const colors = ["red", "green", "blue"];
// ✅ ถูกต้อง
for (let i = 0; i < colors.length; i++) {
console.log(colors[i]);
}
// ❌ วนเกินหนึ่งรอบ
for (let i = 0; i <= colors.length; i++) {
console.log(colors[i]);
}
// ❌ hard-code ทำให้ดูแลยากเมื่อ array เปลี่ยนขนาด
for (let i = 0; i < 3; i++) {
console.log(colors[i]);
}| รูปแบบ | ผลที่ตามมา | ควรใช้ไหม |
|---|---|---|
| `i < arr.length` | วนครบทุกช่องพอดี | ✓ ใช้เป็น default |
| `i <= arr.length` | วนเกินหนึ่งรอบและเสี่ยงได้ `undefined` | ✗ ไม่ควรใช้ |
| `i < 3` | ผูกกับจำนวนตายตัว | ✗ ใช้เฉพาะเมื่อโจทย์กำหนดชัด |
ใช้ `for` เมื่ออยากแก้ค่าใน array โดยตรง
อีกเหตุผลสำคัญที่บทนี้ยังจำเป็นคือ `for` ช่วยให้เราเขียนค่ากลับเข้า array ช่องเดิมได้ตรง ๆ ด้วย `arr[i] = ...` นี่เป็นสิ่งที่ `for...of` ไม่ได้ออกแบบมาเพื่อทำ
แต่ละรอบเราใช้ `i` ระบุช่องเดิม แล้วอัปเดตค่ากลับเข้าไปใน array นั้นทันที
const scores = [70, 82, 91];
for (let i = 0; i < scores.length; i++) {
scores[i] = scores[i] + 5;
}
console.log(scores); // [75, 87, 96]สรุปการเลือกเครื่องมือให้จำง่าย:
- ถ้าไม่ต้องใช้ index ให้ไปบท `for...of กับ array`
- ถ้าต้องใช้ตำแหน่ง, ดูข้อมูลข้างเคียง, หรือแก้ค่าด้วย index ให้อยู่บทนี้
| โจทย์ | ไปบทไหน |
|---|---|
| อ่านค่าทีละตัวจาก array | `for...of กับ array` |
| ต้องใช้ `arr[i]` หรือ index | `for loop กับ array (เมื่อจำเป็นต้องใช้ index)` |
| เผลอคิดจะใช้ `for...in` กับ array | `for...in กับ array` เพื่อดูว่าทำไมไม่ควรใช้ |