แนวทางปฏิบัติที่ดีที่สุดสำหรับการวนรอบใน JavaScript
บทความนี้อธิบายแนวทางปฏิบัติที่ดีที่สุดสำหรับการวนรอบใน JavaScript
YouTube Video
แนวทางปฏิบัติที่ดีที่สุดสำหรับการวนรอบใน JavaScript
ใน JavaScript การใช้ for
loops สำหรับการวนรอบเป็นเรื่องที่พบได้ทั่วไป ที่นี่ เราจะอธิบายรายละเอียดเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ for
loops เพื่อเขียนโค้ดที่มีประสิทธิภาพและอ่านง่าย
เลือกโครงสร้างการวนรอบที่เหมาะสม
JavaScript มีโครงสร้างการวนรอบหลากหลายแบบ ซึ่งแต่ละแบบเหมาะสำหรับวัตถุประสงค์ที่แตกต่างกัน
1// Example of a for loop
2for (let i = 0; i < 5; i++) {
3 console.log(i);
4}
5
6// Example of a for...of loop
7const array = [10, 20, 30];
8for (const value of array) {
9 console.log(value);
10}
11
12// Example of a for...in loop
13const obj = { a: 1, b: 2, c: 3 };
14for (const key in obj) {
15 console.log(`${key}: ${obj[key]}`);
16}
17
18// Example of a while loop
19let count = 0;
20while (count < 5) {
21 console.log(count);
22 count++;
23}
- คำสั่ง
for
เหมาะสมเมื่อจำนวนรอบการวนซ้ำถูกกำหนดไว้ล่วงหน้า - คำสั่ง
for...of
เหมาะสำหรับจัดการอาร์เรย์และวัตถุที่วนซ้ำได้อย่างกระชับ - คำสั่ง
for...in
ใช้สำหรับวนซ้ำบนคุณสมบัติของอ็อบเจกต์ อย่างไรก็ตาม มันไม่เหมาะสำหรับอาร์เรย์ - คำสั่ง
while
และ คำสั่งdo...while
ใช้สำหรับควบคุมลูปตามเงื่อนไข
การใช้เมธอด forEach
และคำสั่ง for...of
เมื่อวนซ้ำผ่านอาร์เรย์ การใช้คำสั่ง for
เพื่อเข้าถึงดัชนีเป็นเรื่องทั่วไป แต่เมธอด forEach
หรือคำสั่ง for...of
อาจอ่านง่ายกว่า
1// Using a standard for loop
2const array = ["apple", "banana", "cherry"];
3for (let i = 0; i < array.length; i++) {
4 console.log(array[i]);
5}
6
7// Using forEach
8array.forEach(item => console.log(item));
9
10// Using for...of
11for (const item of array) {
12 console.log(item);
13}
- คำสั่ง
for
อนุญาตการจัดการดัชนีอย่างชัดเจนขณะวนซ้ำ - เมธอด
forEach
ใช้ฟังก์ชันคอลแบ็กเพื่อประมวลผลแต่ละองค์ประกอบอย่างกระชับ - คำสั่ง
for...of
อ่านได้ง่ายและอนุญาตให้เข้าถึงแต่ละองค์ประกอบในอาร์เรย์โดยตรง
ปรับปรุงเงื่อนไขการวนรอบให้เหมาะสม
เนื่องจากเงื่อนไขการวนรอบจะได้รับการประเมิน repeatedly การหลีกเลี่ยงการคำนวณที่ไม่จำเป็นจะช่วยปรับปรุงประสิทธิภาพ
1const names = ["Alice", "Bob", "Charlie"];
2const scores = [85, 92, 78];
3
4// Inefficient example
5for (let i = 0; i < Math.min(names.length, scores.length); i++) {
6 console.log(`${names[i]} scored ${scores[i]}`);
7}
8
9// Efficient example
10for (let i = 0, len = Math.min(names.length, scores.length); i < len; i++) {
11 console.log(`${names[i]} scored ${scores[i]}`);
12}
- ดังที่แสดงในตัวอย่างนี้ การเก็บผลลัพธ์ของการคำนวณไว้ในตัวแปรล่วงหน้าจะช่วยให้การทำงานของลูปมีประสิทธิภาพมากขึ้น
1const scores = [85, 92, 78];
2let sum = 0;
3let sum2 = 0;
4
5// Inefficient example
6for (let i = 0; i < scores.length; i++) {
7 sum += scores[i];
8}
9console.log(`Total score : ${sum}`);
10
11// Efficient example
12for (let i = scores.length - 1; i >= 0; i--) {
13 sum2 += scores[i];
14}
15console.log(`Total score : ${sum2}`);
- ดังที่แสดงในตัวอย่างนี้ การกลับด้านเงื่อนไขบางครั้งอาจมีประสิทธิภาพมากกว่า
การเพิ่มประสิทธิภาพการประมวลผลลูป
เนื่องจากการประมวลผลลูปถูกดำเนินการซ้ำ การหลีกเลี่ยงการคำนวณที่ไม่จำเป็นสามารถปรับปรุงประสิทธิภาพได้
1const array = ["apple", "banana", "cherry"];
2
3// Inefficient example
4for (let i = 0; i < 100; i++) {
5 const element = document.querySelector("#myElement");
6 element.textContent = `Count: ${i}`;
7}
8
9// Efficient example
10const element = document.querySelector("#myElement");
11for (let i = 0; i < 100; i++) {
12 element.textContent = `Count: ${i}`;
13}
- ในตัวอย่างนี้ โดยการย้ายเมธอด
querySelector
ออกนอกลูป ทำให้การคำนวณซ้ำที่ไม่จำเป็นถูกกำจัดออก
ตระหนักถึงช่วงการเข้าถึงตัวแปร (Scope)
ใช้ let
หรือ const
เพื่อให้แน่ใจว่าตัวแปรภายในลูปมีช่วงการเข้าถึงที่เหมาะสม เนื่องจาก var
ถูกจำกัดให้อยู่ในช่วงฟังก์ชัน มันอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด
1// Using let
2for (let i = 0; i < 3; i++) {
3 console.log(i);
4}
5
6// Potential issue with var
7for (var i = 0; i < 3; i++) {
8 setTimeout(() => console.log(i), 1000); // 3, 3, 3
9}
10
11// Using let to avoid the issue
12for (let i = 0; i < 3; i++) {
13 setTimeout(() => console.log(i), 1000); // 0, 1, 2
14}
var
มีขอบเขตเป็นแบบฟังก์ชัน ดังนั้นหลังจบลูปค่าi
คือ3
และฟังก์ชันที่ถูก execute โดยsetTimeout
จะให้ผลลัพธ์เป็น3
- การใช้
let
ค่าi
ภายในฟังก์ชัน callback ของsetTimeout
จะอ้างอิงถึงค่าที่ใหม่สำหรับแต่ละลูป ดังนั้นผลลัพธ์ที่ได้คือ0, 1, 2
ตามที่คาดไว้
ปรับปรุงความสามารถในการอ่านด้วยการออกจากลูปล่วงหน้า
เพื่อทำให้การประมวลผลลูปง่ายขึ้น ใช้ break
และ continue
ให้เหมาะสมเพื่อเพิ่มความสามารถในการอ่าน
1// Example using break
2for (let i = 0; i < 10; i++) {
3 if (i === 5) {
4 break; // Exit the loop
5 }
6 console.log(i);
7}
8
9// Example using continue
10for (let i = 0; i < 10; i++) {
11 if (i % 2 === 0) {
12 continue; // Skip to the next iteration
13 }
14 console.log(i);
15}
- การใช้
break
ช่วยให้คุณสามารถหยุดการประมวลผลลูปกลางทาง โดยข้ามการวนซ้ำทั้งหมดที่ตามมา - การใช้
continue
ช่วยให้คุณสามารถข้ามการประมวลผลในลูปปัจจุบันและไปยังการวนซ้ำถัดไป
หลีกเลี่ยงการซ้อนลูปลึก
การซ้อนลูปลึกทำให้โค้ดอ่านยากขึ้น ดังนั้นควรพยายามทำให้การซ้อนลูปเป็นไปอย่างตื้นด้วยการใช้การออกจากลูปล่วงหน้าหรือแบ่งฟังก์ชันการทำงานออกเป็นฟังก์ชันแยก
1// Deeply nested example
2for (let i = 0; i < 5; i++) {
3 for (let j = 0; j < 5; j++) {
4 if (i + j > 5) {
5 console.log(i, j);
6 }
7 }
8}
9
10// Improved using function decomposition
11function processPairs(i) {
12 for (let j = 0; j < 5; j++) {
13 if (i + j > 5) {
14 console.log(i, j);
15 }
16 }
17}
18
19for (let i = 0; i < 5; i++) {
20 processPairs(i);
21}
- ในตัวอย่างนี้ ใช้ฟังก์ชันเพื่อลดการซ้อนลึกของโค้ด
พิจารณาการจัดการข้อผิดพลาด
หากมีความเป็นไปได้ที่จะเกิดข้อผิดพลาดในลูป ให้ดำเนินการจัดการข้อผิดพลาดอย่างเหมาะสม
1const data = ["123", "abc", "456", "xyz"];
2
3// Without Error Handling
4for (const item of data) {
5 const result = parseInt(item);
6 console.log(`Parsed value: ${result}`);
7}
8
9// With Error Handling
10for (const item of data) {
11 try {
12 const result = parseInt(item);
13 if (isNaN(result)) {
14 throw new Error(`Invalid number: ${item}`);
15 }
16 console.log(`Parsed value: ${result}`);
17 } catch (error) {
18 console.error(`Error processing item: ${item}. ${error.message}`);
19 }
20}
- ในตัวอย่างนี้ การจัดการข้อผิดพลาดถูกใช้สำหรับการประมวลผลข้อมูลที่ไม่ถูกต้อง การตรวจจับและรายงานปัญหา
จุดที่ควรทราบในการประมวลผลแบบอะซินโครนัส
เมื่อจัดการการประมวลผลแบบอะซินโครนัสในลูป การใช้ async/await
สามารถทำให้โค้ดกระชับและเข้าใจง่าย
1const urls = ["https://example.com/1", "https://example.com/2"];
2
3// Proper handling of asynchronous operations
4async function fetchUrls() {
5 for (const url of urls) {
6 const response = await fetch(url);
7 const data = await response.json();
8 console.log(data);
9 }
10}
11
12fetchUrls();
- โค้ดนี้ดึง URL จากอาเรย์
urls
แบบอะซิงโครนัสทีละตัวและประมวลผลผลลัพธ์ในรูปแบบ JSON การใช้async/await
ทำให้งานอะซิงโครนัสง่ายขึ้น โดยดึงข้อมูลสำหรับแต่ละ URL ตามลำดับและแสดงผลในคอนโซล
ทำความเข้าใจความแตกต่างระหว่างคำสั่ง for...of
และ forEach()
ในการประมวลผลแบบอะซิงโครนัส
1async function asyncTask(num) {
2 return new Promise(resolve => {
3 setTimeout(() => {
4 console.log(`Task ${num} done`);
5 resolve();
6 }, 100);
7 });
8}
9
10async function runWithForOf() {
11 console.log("Start for...of");
12 for (const num of [1, 2, 3]) {
13 await asyncTask(num);
14 }
15 console.log("End for...of");
16}
17
18async function runWithForEach() {
19 console.log("Start forEach");
20 [1, 2, 3].forEach(async num => {
21 await asyncTask(num);
22 });
23 console.log("End forEach");
24}
25
26async function executeExamples() {
27 await runWithForOf();
28 await runWithForEach();
29}
30
31executeExamples();
-
เมื่อจัดการการประมวลผลแบบอะซิงโครนัสในลูป ให้สังเกตความแตกต่างในพฤติกรรมตามตัวอย่างนี้ระหว่างการใช้
for...of
กับasync/await
และการใช้forEach()
-
การใช้
for...of
จะทำให้โค้ดถูกประมวลผลแบบลำดับและรอที่คำสั่งawait
ภายในลูปก่อนจะดำเนินการรอบถัดไป ในทางกลับกันforEach()
จะดำเนินการประมวลผลแบบขนาน
สรุป
for
statement ใน JavaScript เป็นเครื่องมือที่เรียบง่ายแต่ทรงพลัง ด้วยการนำแนวปฏิบัติที่ดีที่ได้แนะนำในที่นี้ไปใช้ คุณสามารถเขียนโค้ดที่มีประสิทธิภาพและอ่านง่ายได้ ให้ความสำคัญกับการเลือกโครงสร้างลูปที่เหมาะสม การจัดการขอบเขต การจัดการข้อผิดพลาด และมุ่งเน้นการเขียนโค้ดที่ดูแลรักษาได้ง่าย
คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย