แนวทางปฏิบัติที่ดีที่สุดสำหรับการวนรอบใน JavaScript

แนวทางปฏิบัติที่ดีที่สุดสำหรับการวนรอบใน 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 ด้วย

YouTube Video