Các phương pháp hay nhất cho việc lặp lại trong JavaScript

Các phương pháp hay nhất cho việc lặp lại trong JavaScript

Bài viết này giải thích các phương pháp hay nhất cho việc lặp lại trong JavaScript.

YouTube Video

Các phương pháp hay nhất cho việc lặp lại trong JavaScript

Trong JavaScript, việc sử dụng vòng lặp for để lặp lại là phổ biến. Tại đây, chúng ta sẽ cung cấp giải thích chi tiết về các phương pháp hay nhất trong việc sử dụng vòng lặp for để viết mã hiệu quả và dễ đọc.

Chọn cấu trúc vòng lặp phù hợp

JavaScript cung cấp nhiều cấu trúc vòng lặp, mỗi loại phù hợp với mục đích khác nhau.

 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}
  • Câu lệnh for phù hợp khi số lần lặp được xác định trước.
  • Câu lệnh for...of phù hợp để xử lý ngắn gọn các mảng và đối tượng có thể duyệt.
  • Câu lệnh for...in được sử dụng để duyệt qua các thuộc tính của đối tượng. Tuy nhiên, nó không phù hợp cho mảng.
  • Câu lệnh whilecâu lệnh do...while được sử dụng để điều khiển vòng lặp dựa trên các điều kiện.

Sử dụng phương thức forEach và câu lệnh for...of

Khi lặp qua một mảng, việc sử dụng câu lệnh for để truy cập chỉ mục là phổ biến, nhưng phương thức forEach hoặc câu lệnh for...of có thể dễ đọc hơn.

 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}
  • Câu lệnh for cho phép quản lý chỉ mục rõ ràng khi lặp.
  • Phương thức forEach sử dụng hàm gọi lại để xử lý từng phần tử một cách ngắn gọn.
  • Câu lệnh for...of có tính dễ đọc cao và cho phép truy cập trực tiếp vào từng phần tử trong mảng.

Tối ưu hóa điều kiện vòng lặp

Vì điều kiện vòng lặp được đánh giá nhiều lần, tránh các phép tính không cần thiết có thể cải thiện hiệu suất.

 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}
  • Như được minh họa trong ví dụ này, lưu trữ kết quả tính toán vào một biến trước sẽ cho phép thực thi vòng lặp hiệu quả hơn.
 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}`);
  • Như được minh họa trong ví dụ này, đôi khi việc đảo điều kiện có thể hiệu quả hơn.

Tối ưu hóa xử lý vòng lặp

Vì xử lý vòng lặp được thực hiện lặp đi lặp lại, tránh các tính toán không cần thiết có thể cải thiện hiệu suất.

 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}
  • Trong ví dụ này, bằng cách chuyển phương thức querySelector ra ngoài vòng lặp, các phép tính lặp đi lặp lại không cần thiết được loại bỏ.

Chú ý đến phạm vi biến

Sử dụng let hoặc const để đảm bảo biến bên trong vòng lặp có phạm vi phù hợp. Do var bị giới hạn trong phạm vi hàm, nó có thể gây ra hành vi không mong muốn.

 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 có phạm vi trong hàm, vì vậy sau vòng lặp giá trị của i3, và tất cả các hàm được thực thi bởi setTimeout đều xuất ra 3.
  • Sử dụng let, giá trị i bên trong hàm callback của setTimeout tham chiếu đến một giá trị mới cho mỗi vòng lặp, vì vậy kết quả 0, 1, 2 như mong đợi.

Cải thiện tính dễ đọc bằng cách thoát sớm

Để đơn giản hóa xử lý vòng lặp, sử dụng breakcontinue một cách phù hợp để tăng cường tính dễ đọc.

 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}
  • Sử dụng break cho phép bạn kết thúc quá trình xử lý vòng lặp giữa chừng, bỏ qua tất cả các lần lặp tiếp theo.
  • Sử dụng continue cho phép bạn bỏ qua quá trình vòng lặp hiện tại và chuyển sang lần lặp kế tiếp.

Tránh lồng ghép sâu

Lồng ghép sâu khiến mã khó đọc hơn, vì vậy hãy cố gắng giữ lồng ghép ở mức nông bằng cách sử dụng trả về sớm hoặc chia chức năng thành các hàm riêng biệt.

 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}
  • Trong ví dụ này, các hàm được sử dụng để giảm độ lồng nhau.

Hãy xem xét xử lý lỗi

Nếu có khả năng xảy ra lỗi trong vòng lặp, hãy triển khai xử lý lỗi thích hợp.

 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}
  • Trong ví dụ này, xử lý lỗi được thực hiện để xử lý dữ liệu không hợp lệ, phát hiện và báo cáo các vấn đề.

Những điểm cần lưu ý trong xử lý bất đồng bộ

Khi xử lý bất đồng bộ trong vòng lặp, sử dụng async/await có thể tạo ra mã ngắn gọn và dễ hiểu.

 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();
  • Mã này lấy bất đồng bộ các URL từ mảng urls từng cái một và xử lý kết quả dưới định dạng JSON. Sử dụng async/await giúp đơn giản hóa các thao tác bất đồng bộ, tuần tự lấy dữ liệu cho từng URL và xuất ra console.

Hiểu sự khác biệt giữa câu lệnh for...offorEach() trong xử lý bất đồng bộ.

 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();
  • Khi xử lý bất đồng bộ trong các vòng lặp, hãy lưu ý sự khác biệt trong hành vi, như trong ví dụ này, giữa việc sử dụng for...of với async/await và sử dụng forEach().

  • Với for...of, mã sẽ được thực thi tuần tự và dừng lại ở await bên trong vòng lặp trước khi tiếp tục đến vòng lặp kế tiếp. Mặt khác, forEach() thực thi các xử lý một cách song song.

Kết luận

for trong JavaScript là một công cụ đơn giản nhưng mạnh mẽ. Bằng cách áp dụng các phương pháp tốt nhất được giới thiệu ở đây, bạn có thể viết mã hiệu quả và dễ đọc. Hãy chú ý chọn cấu trúc vòng lặp phù hợp, quản lý phạm vi, xử lý lỗi, và hướng tới viết mã dễ bảo trì.

Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.

YouTube Video