Article · programming
JavaScript พื้นฐาน EP. 4: Array และ Loop
JavaScript
เรียนรู้การจัดเก็บข้อมูลหลายรายการด้วย Array และการใช้ for, while, for...of รวมถึงเมธอด map, filter และ reduce เพื่อประมวลผลข้อมูลอย่างเป็นระบบ
1. ทำไมเราต้องมี Array
จาก EP ก่อนหน้า เราได้เรียนรู้การใช้ตัวแปร เงื่อนไข และฟังก์ชันแล้ว แต่ถ้าต้องเก็บชื่อสินค้า 100 รายการ การสร้างตัวแปรแยกกัน 100 ตัวคงไม่สะดวก JavaScript จึงมี Array สำหรับจัดเก็บข้อมูลหลายรายการไว้ในตัวแปรเดียว และช่วยให้เราค้นหา แก้ไข หรือประมวลผลข้อมูลเหล่านั้นได้ง่ายขึ้น
const fruits = ['มะม่วง', 'ส้ม', 'กล้วย'];
console.log(fruits);
console.log(fruits.length);
ตัวแปร `fruits` เก็บข้อมูลสามรายการ ส่วน `.length` ใช้นับจำนวนสมาชิกใน Array ดังนั้นผลลัพธ์ของ `fruits.length` คือ 3 การใช้ Array ทำให้เราจัดการรายการข้อมูลได้โดยไม่ต้องประกาศตัวแปรแยกทีละรายการ
แนวคิดสำคัญArray เป็นชุดข้อมูลที่เรียงลำดับสมาชิก โดยตำแหน่งเริ่มต้นใช้ index 0 ไม่ใช่ 1
2. การเข้าถึงสมาชิกด้วย index
เราสามารถเข้าถึงสมาชิกแต่ละตำแหน่งโดยใช้ชื่อตัวแปรตามด้วยวงเล็บเหลี่ยม เช่น `fruits[0]` หมายถึงสมาชิกตัวแรก และ `fruits[2]` หมายถึงสมาชิกตัวที่สาม หากเข้าถึง index ที่ไม่มีสมาชิกอยู่ จะได้ค่า `undefined`
const fruits = ['มะม่วง', 'ส้ม', 'กล้วย'];
console.log(fruits[0]);
console.log(fruits[1]);
console.log(fruits[2]);
console.log(fruits[3]);
| Index | ค่า | คำอธิบาย |
|---|---|---|
| 0 | มะม่วง | สมาชิกตัวแรก |
| 1 | ส้ม | สมาชิกตัวที่สอง |
| 2 | กล้วย | สมาชิกตัวที่สาม |
| 3 | undefined | ไม่มีสมาชิกในตำแหน่งนี้ |
แก้ไขและเพิ่มข้อมูล
เมื่อประกาศ Array ด้วย `const` เราไม่สามารถกำหนดตัวแปรให้ชี้ไปยัง Array ตัวใหม่ได้ แต่ยังสามารถแก้ไขสมาชิกหรือเพิ่มสมาชิกใน Array เดิมได้ หากต้องการเปลี่ยนชุดข้อมูลทั้งชุดด้วยการกำหนดค่าใหม่ให้ใช้ `let`
const fruits = ['มะม่วง', 'ส้ม'];
fruits[1] = 'แตงโม';
fruits.push('กล้วย');
console.log(fruits);
console.log(fruits.length);
คำสั่ง `push()` เพิ่มสมาชิกต่อท้าย Array ส่วนการกำหนดค่าให้ `fruits[1]` เป็นการเปลี่ยนสมาชิกตำแหน่งที่สอง หลังทำงานเสร็จ Array นี้จะมีข้อมูลสามรายการ ได้แก่ มะม่วง แตงโม และกล้วย
3. เมธอด Array ที่ใช้บ่อย
JavaScript มีเมธอดสำเร็จรูปสำหรับจัดการรายการข้อมูล เมธอดแต่ละตัวมีหน้าที่ต่างกัน เช่น เพิ่มสมาชิก ลบสมาชิก ค้นหาข้อมูล หรือแปลงข้อมูลเป็นรูปแบบใหม่
| เมธอด | หน้าที่ | ตัวอย่าง |
|---|---|---|
| push() | เพิ่มสมาชิกท้าย Array | items.push('A') |
| pop() | นำสมาชิกตัวท้ายออก | items.pop() |
| includes() | ตรวจว่ามีค่านั้นหรือไม่ | items.includes('A') |
| indexOf() | ค้นหา index ของค่าแรกที่ตรงกัน | items.indexOf('A') |
| slice() | คัดลอกข้อมูลบางช่วงโดยไม่แก้ Array ต้นฉบับ | items.slice(0, 2) |
| join() | รวมสมาชิกเป็นข้อความ | items.join(', ') |
const colors = ['แดง', 'เขียว', 'น้ำเงิน'];
console.log(colors.includes('เขียว'));
console.log(colors.indexOf('น้ำเงิน'));
console.log(colors.slice(0, 2));
console.log(colors.join(' - '));
ระวังเมธอดที่เปลี่ยนข้อมูล`push()` และ `pop()` เปลี่ยน Array เดิม ส่วน `slice()` คืนค่าเป็น Array ใหม่โดยไม่ลบสมาชิกจาก Array ต้นฉบับ ควรเลือกใช้ให้ตรงกับสิ่งที่ต้องการ
4. Loop คืออะไร
Loop หรือการวนซ้ำ คือการสั่งให้โปรแกรมทำงานบางอย่างหลายครั้ง เช่น แสดงชื่อผลไม้ทุกตัว คำนวณยอดขายทุกสินค้า หรือค้นหาข้อมูลที่ตรงกับเงื่อนไข การใช้ลูปช่วยลดการเขียนคำสั่งซ้ำและทำให้รองรับข้อมูลจำนวนมากได้ดีขึ้น
ใช้ for เมื่อรู้จำนวนรอบหรือมี index
const fruits = ['มะม่วง', 'ส้ม', 'กล้วย'];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
ลูป `for` มีสามส่วนสำคัญ ได้แก่ การกำหนดค่าเริ่มต้น `let i = 0` เงื่อนไข `i < fruits.length` และการเพิ่มค่า `i++` ทุกครั้งที่วนครบหนึ่งรอบ โปรแกรมจะตรวจสอบเงื่อนไขก่อนทำงาน หากเงื่อนไขเป็นเท็จก็จะหยุดวนซ้ำ
ใช้ for...of เมื่อไม่ต้องการ index
หากต้องการเพียงอ่านสมาชิกแต่ละตัวโดยไม่จำเป็นต้องรู้ตำแหน่ง `for...of` มักจะอ่านง่ายกว่า และช่วยลดโอกาสเขียนเงื่อนไข index ผิดพลาด
const fruits = ['มะม่วง', 'ส้ม', 'กล้วย'];
for (const fruit of fruits) {
console.log(fruit);
}
ใช้ while เมื่อวนตามเงื่อนไข
ลูป `while` จะทำงานตราบใดที่เงื่อนไขเป็นจริง เหมาะกับสถานการณ์ที่จำนวนรอบไม่ได้กำหนดไว้ชัดเจน แต่ต้องแน่ใจว่าภายในลูปมีโอกาสทำให้เงื่อนไขเป็นเท็จ มิฉะนั้นอาจเกิดลูปไม่รู้จบ
let count = 1;
while (count <= 5) {
console.log(`รอบที่ ${count}`);
count++;
}
ข้อควรระวัง: Infinite Loopหากเงื่อนไขของลูปเป็นจริงตลอดเวลา เช่น ลืมเพิ่มค่าตัวแปร `count` ในตัวอย่าง while โปรแกรมอาจทำงานไม่สิ้นสุดและทำให้หน้าเว็บหรือกระบวนการทำงานช้าลงได้
5. ใช้ map เพื่อแปลงข้อมูล
`map()` ใช้สร้าง Array ใหม่จากสมาชิกเดิม โดยนำแต่ละรายการไปผ่านฟังก์ชันแปลงค่า เหมาะกับการแปลงราคาสินค้า คำนวณคะแนน หรือเลือกสร้างข้อมูลรูปแบบใหม่จากข้อมูลที่มีอยู่
const prices = [100, 250, 400];
const pricesWithTax = prices.map(price => price * 1.07);
console.log(pricesWithTax);
console.log(prices);
ตัวอย่างนี้คำนวณราคาโดยเพิ่ม 7% ให้แต่ละรายการ และสร้าง Array ใหม่ในตัวแปร `pricesWithTax` ส่วน `prices` ยังคงเป็นข้อมูลราคาเดิม เพราะ `map()` ไม่ได้เปลี่ยนสมาชิกตัวเลขใน Array ต้นฉบับ
6. ใช้ filter เพื่อคัดเลือกข้อมูล
`filter()` ใช้เลือกสมาชิกที่ผ่านเงื่อนไข และคืนค่าเป็น Array ใหม่ที่มีเฉพาะรายการที่ผ่านการตรวจสอบ หากไม่มีรายการใดผ่าน เงื่อนไขจะคืน Array ว่าง
const scores = [35, 82, 49, 90, 67];
const passingScores = scores.filter(score => score >= 50);
console.log(passingScores);
console.log(scores);
ผลลัพธ์ `passingScores` คือ `[82, 90, 67]` เพราะมีคะแนนตั้งแต่ 50 ขึ้นไป ส่วน Array `scores` ยังคงมีสมาชิกครบทั้งห้ารายการ
7. ใช้ reduce เพื่อรวมข้อมูล
`reduce()` ใช้รวมสมาชิกใน Array ให้กลายเป็นผลลัพธ์เดียว เช่น ผลรวมคะแนน ยอดขาย หรือจำนวนเงินทั้งหมด โดยฟังก์ชันจะรับค่าที่สะสมไว้และสมาชิกปัจจุบันในแต่ละรอบ
const prices = [120, 80, 150, 50];
const total = prices.reduce((sum, price) => {
return sum + price;
}, 0);
console.log(`ยอดรวม ${total} บาท`);
ค่าเริ่มต้น `0` เป็นค่าตั้งต้นของตัวสะสม `sum` จากนั้นแต่ละรอบจะนำราคาเข้ามาบวกสะสมจนได้ผลรวม 400 บาท การระบุค่าเริ่มต้นอย่างชัดเจนยังช่วยให้จัดการ Array ว่างได้ง่ายขึ้น
8. เปรียบเทียบ for, map, filter และ reduce
| เครื่องมือ | ผลลัพธ์หลัก | เหมาะกับงาน |
|---|---|---|
| for | ขึ้นอยู่กับคำสั่งภายในลูป | ควบคุม index และลำดับการทำงาน |
| for...of | ขึ้นอยู่กับคำสั่งภายในลูป | อ่านสมาชิกทีละรายการ |
| map() | Array ใหม่ | แปลงสมาชิกทุกตัว |
| filter() | Array ใหม่ | เลือกสมาชิกที่ผ่านเงื่อนไข |
| reduce() | ค่าผลลัพธ์สะสม | รวมข้อมูลเป็นผลลัพธ์เดียว |
หลักการเลือกใช้งานหากต้องการแปลงข้อมูลทุกตัวให้ใช้ `map()` หากต้องการคัดกรองข้อมูลให้ใช้ `filter()` หากต้องการรวมเป็นค่าเดียวให้พิจารณา `reduce()` และหากต้องการควบคุมขั้นตอนอย่างละเอียดให้ใช้ลูปที่เหมาะสม
9. ตัวอย่างจริง: สรุปยอดขายสินค้า
ลองนำ Array และเมธอดต่าง ๆ มาประยุกต์กับข้อมูลสินค้า โดยแต่ละรายการมีชื่อสินค้า ราคา และจำนวนที่ขายได้ เราจะคำนวณยอดขายของแต่ละรายการ เลือกสินค้าที่มียอดขายถึงเกณฑ์ และหายอดขายรวมทั้งหมด
const products = [
{ name: 'สมุด', price: 25, quantity: 20 },
{ name: 'ปากกา', price: 12, quantity: 50 },
{ name: 'กระเป๋า', price: 350, quantity: 4 },
{ name: 'ดินสอ', price: 8, quantity: 100 }
];
const sales = products.map(product => ({
name: product.name,
total: product.price * product.quantity
}));
const highSales = sales.filter(item => item.total >= 300);
const grandTotal = sales.reduce((sum, item) => {
return sum + item.total;
}, 0);
console.log('ยอดขายแต่ละรายการ:', sales);
console.log('รายการยอดขายตั้งแต่ 300 บาท:', highSales);
console.log('ยอดขายรวม:', grandTotal);
ตัวอย่างนี้แยกการทำงานเป็นสามขั้นตอนอย่างชัดเจน ได้แก่ `map()` เพื่อคำนวณยอดขายแต่ละรายการ `filter()` เพื่อเลือกสินค้าที่มียอดขายอย่างน้อย 300 บาท และ `reduce()` เพื่อรวมยอดขายทั้งหมด วิธีนี้ช่วยให้อ่านและตรวจสอบแต่ละขั้นตอนได้ง่าย
10. ข้อผิดพลาดที่พบบ่อย
| ข้อผิดพลาด | สาเหตุ | แนวทางแก้ไข |
|---|---|---|
| วนลูปเกินจำนวนสมาชิก | ใช้เงื่อนไข `i <= array.length` | โดยทั่วไปให้ใช้ `i < array.length` |
| อ่านสมาชิกได้ undefined | เรียก index ที่ไม่มีข้อมูล | ตรวจสอบ index และจำนวนสมาชิก |
| ลูปไม่หยุด | เงื่อนไขไม่เปลี่ยนเป็น false | ตรวจสอบการปรับค่าตัวแปรในลูป |
| ใช้ map แทน filter | ต้องการคัดกรองแต่กลับแปลงข้อมูลทุกตัว | เลือกเมธอดตามผลลัพธ์ที่ต้องการ |
| reduce ได้ผลรวมผิด | กำหนดค่าเริ่มต้นหรือสูตรสะสมไม่ถูกต้อง | ตรวจสอบค่าเริ่มต้นและการคำนวณในแต่ละรอบ |
11. แบบฝึกหัดท้ายบท
กำหนด Array คะแนน `[45, 78, 92, 33, 67, 88]` แล้วทดลองทำโจทย์ต่อไปนี้: 1) แสดงคะแนนทุกตัวด้วย `for...of` 2) สร้าง Array ใหม่ที่เก็บคะแนนตั้งแต่ 60 ขึ้นไปด้วย `filter()` 3) สร้าง Array ใหม่ที่เพิ่มคะแนนทุกตัวอีก 5 คะแนนด้วย `map()` 4) หาผลรวมคะแนนทั้งหมดด้วย `reduce()`
const scores = [45, 78, 92, 33, 67, 88];
for (const score of scores) {
console.log(score);
}
const passed = scores.filter(score => score >= 60);
const bonusScores = scores.map(score => score + 5);
const total = scores.reduce((sum, score) => sum + score, 0);
console.log('คะแนนตั้งแต่ 60 ขึ้นไป:', passed);
console.log('คะแนนหลังเพิ่ม 5:', bonusScores);
console.log('ผลรวมคะแนน:', total);
ตรวจคำตอบคะแนนที่ผ่านเกณฑ์ 60 คือ 78, 92, 67 และ 88 ส่วนผลรวมคะแนนเดิมเท่ากับ 403 และ Array คะแนนหลังเพิ่ม 5 คือ 50, 83, 97, 38, 72 และ 93
12. สรุปและเตรียมพร้อมสำหรับ EP ถัดไป
Array ช่วยให้จัดเก็บข้อมูลหลายรายการอย่างเป็นระบบ ส่วน Loop ช่วยให้ทำงานกับข้อมูลเหล่านั้นซ้ำได้อย่างมีประสิทธิภาพ เราได้เรียนรู้การใช้ index การเพิ่มและค้นหาสมาชิก รวมถึงการใช้ `map()`, `filter()` และ `reduce()` เพื่อแปลง คัดเลือก และรวมข้อมูล
เมื่อจัดการข้อมูลเป็นชุดได้ เราจะเปลี่ยนจากการเขียนคำสั่งซ้ำ ๆ ไปสู่การสร้างกระบวนการที่ยืดหยุ่นและขยายต่อได้
EP. 5: Object และการจัดการข้อมูลแบบมีโครงสร้างตอนต่อไปเราจะเรียนรู้ Object ซึ่งช่วยเก็บข้อมูลที่เกี่ยวข้องกันไว้ในรูปแบบคุณสมบัติและค่า เช่น ข้อมูลผู้ใช้หรือสินค้า พร้อมฝึกอ่าน เพิ่ม แก้ไข และนำ Object มาใช้งานร่วมกับ Array
อ่านจนถึงระยะ 500px ก่อนท้ายหน้าและอยู่ในหน้านี้อย่างน้อย 5 นาที เพื่อรับ EXP วันละครั้ง
⏳ กำลังจับเวลาอ่าน...