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
while
và câu lệnhdo...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ủai
là3
, và tất cả các hàm được thực thi bởisetTimeout
đều xuất ra3
.- Sử dụng
let
, giá trịi
bên trong hàm callback củasetTimeout
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 break
và continue
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ụngasync/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...of
và forEach()
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ớiasync/await
và sử dụngforEach()
. -
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.