Tìm hiểu về cách đóng JavaScript trong vòng lặp: Ví dụ thực tế

JavaScript

Làm sáng tỏ việc đóng vòng lặp trong JavaScript

Các nhà phát triển JavaScript thường gặp phải hành vi không mong muốn khi sử dụng các bao đóng bên trong các vòng lặp. Vấn đề này có thể dẫn đến nhầm lẫn, đặc biệt đối với những người chưa quen với khái niệm bao đóng.

Trong bài viết này, chúng ta sẽ khám phá các ví dụ thực tế minh họa những cạm bẫy phổ biến và cung cấp giải pháp sử dụng các bao đóng hiệu quả trong vòng lặp, cho dù xử lý trình xử lý sự kiện, mã không đồng bộ hay lặp qua mảng.

Yêu cầu Sự miêu tả
let Khai báo một biến cục bộ có phạm vi khối, tùy ý khởi tạo nó thành một giá trị. Được sử dụng để đảm bảo rằng mỗi lần lặp của vòng lặp đều có phạm vi riêng.
const Khai báo một hằng số có tên chỉ đọc, có phạm vi khối. Được sử dụng để tạo một hàm hoặc biến có giá trị không thay đổi.
Promise Thể hiện sự hoàn thành (hoặc thất bại) cuối cùng của một hoạt động không đồng bộ và giá trị kết quả của nó.
setTimeout Gọi một hàm hoặc đánh giá một biểu thức sau một số mili giây được chỉ định.
addEventListener Đính kèm trình xử lý sự kiện vào một phần tử được chỉ định mà không ghi đè trình xử lý sự kiện hiện có.
IIFE Biểu thức hàm được gọi ngay lập tức. Một hàm chạy ngay khi được xác định. Được sử dụng để tạo phạm vi cục bộ trong các vòng lặp.
for...in Lặp lại các thuộc tính có thể đếm được của một đối tượng, theo thứ tự tùy ý.
for...of Lặp lại các giá trị của một đối tượng có thể lặp lại (như một mảng hoặc một chuỗi), theo một thứ tự cụ thể.

Tìm hiểu về việc đóng JavaScript trong vòng lặp

Các tập lệnh được cung cấp trong các ví dụ trước giải quyết vấn đề phổ biến về việc đóng trong vòng lặp trong JavaScript. Khi sử dụng một khai báo trong một vòng lặp, tất cả các lần lặp đều có chung phạm vi hàm. Đây là lý do tại sao, trong ví dụ đầu tiên, kết quả đầu ra là "Giá trị của tôi: 3" ba lần. Giải pháp là sử dụng , tạo ra một phạm vi khối duy trì giá trị chính xác cho mỗi lần lặp. Cách tiếp cận này đảm bảo rằng mỗi lần lặp có phạm vi riêng, do đó giữ nguyên giá trị chính xác khi hàm được gọi. Kịch bản lệnh trình bày cách thay đổi khai báo từ ĐẾN let khắc phục sự cố và ghi lại "Giá trị của tôi: 0", "Giá trị của tôi: 1" và "Giá trị của tôi: 2" như dự định.

Đối với mã không đồng bộ, vấn đề đóng tương tự có thể phát sinh. sử dụng Và chức năng với đảm bảo rằng mỗi cuộc gọi không đồng bộ duy trì giá trị lặp lại chính xác. Kịch bản cho thấy rằng bằng cách sử dụng wait với , mỗi lời hứa được giải quyết sẽ ghi lại giá trị mong đợi. Người nghe sự kiện cũng có thể gặp phải vấn đề tương tự; tuy nhiên, gói chức năng nghe trong một (Biểu thức hàm được gọi ngay lập tức) giúp thu được giá trị chính xác bằng cách tạo phạm vi mới cho mỗi lần lặp. Việc sử dụng Và for...of các vòng lặp tiếp tục thể hiện tầm quan trọng của việc xác định phạm vi trong các bao đóng, trình bày cách nắm bắt chính xác chỉ mục và giá trị bằng cách sử dụng để tạo phạm vi riêng biệt cho mỗi lần lặp vòng lặp.

Giải quyết các vấn đề về đóng trong vòng lặp JavaScript bằng let

JavaScript (ES6)

let funcs = [];
// Let's create 3 functions
for (let i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value:", i);
  };
}
for (let j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

Đảm bảo giá trị đóng chính xác trong mã không đồng bộ

JavaScript (ES6)

const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
for (let i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
}

Đóng chính xác trong Trình xử lý sự kiện bằng IIFE

JavaScript (ES6)

var buttons = document.getElementsByTagName("button");
// Let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
  // as event listeners
  (function(i) {
    buttons[i].addEventListener("click", function() {
      // each should log its value.
      console.log("My value:", i);
    });
  })(i);
}

Đóng đúng với vòng lặp for...in và for...of

JavaScript (ES6)

const arr = [1, 2, 3];
const fns = [];
for (const i in arr) {
  fns.push(((i) => () => console.log("index:", i))(i));
}
for (const v of arr) {
  fns.push(((v) => () => console.log("value:", v))(v));
}
for (const n of arr) {
  const obj = { number: n };
  fns.push(((n, obj) => () => console.log("n:", n, "|", "obj:", JSON.stringify(obj)))(n, obj));
}
for (const f of fns) {
  f();
}

Khám phá việc sử dụng các bao đóng trong các hàm JavaScript nâng cao

Bao đóng là một khái niệm cơ bản trong JavaScript cho phép một hàm truy cập các biến từ phạm vi kèm theo của nó, ngay cả sau khi phạm vi đó đã đóng. Tính năng này đặc biệt mạnh mẽ khi tạo các hàm nâng cao chẳng hạn như các hàm được sử dụng trong ghi nhớ, cà ri và lập trình hàm. Ví dụ: tính năng ghi nhớ tận dụng các bao đóng để ghi nhớ kết quả của các lệnh gọi hàm đắt tiền và trả về kết quả được lưu trong bộ nhớ đệm khi các đầu vào tương tự xảy ra lần nữa. Bằng cách sử dụng các bao đóng, chúng ta có thể tạo mã hiệu quả và tối ưu hơn để nâng cao hiệu suất, đặc biệt là trong các hàm đệ quy như tính toán chuỗi Fibonacci.

Một cách sử dụng nâng cao khác của các bao đóng là tạo các biến và hàm riêng tư trong các đối tượng JavaScript, mô phỏng các phương thức và thuộc tính riêng tư. Kỹ thuật này thường được sử dụng trong các mẫu mô-đun và các biểu thức hàm được gọi ngay lập tức (IIFE) để đóng gói chức năng và tránh làm ô nhiễm phạm vi toàn cục. Hơn nữa, các bao đóng đóng một vai trò quan trọng trong việc xử lý sự kiện và lập trình không đồng bộ, nơi chúng giúp duy trì trạng thái và bối cảnh theo thời gian. Hiểu và sử dụng hiệu quả các bao đóng có thể nâng cao đáng kể các kỹ năng lập trình JavaScript của bạn và cho phép bạn viết mã mô-đun hơn, có thể tái sử dụng và bảo trì nhiều hơn.

  1. Bao đóng trong JavaScript là gì?
  2. Bao đóng là một hàm duy trì quyền truy cập vào phạm vi từ vựng của nó, ngay cả khi hàm được thực thi bên ngoài phạm vi đó.
  3. Tại sao việc đóng cửa xảy ra trong các vòng lặp?
  4. Việc đóng trong vòng lặp xảy ra do vòng lặp tạo ra các hàm thu thập cùng một tham chiếu biến, dẫn đến hành vi không mong muốn nếu không được xử lý đúng cách.
  5. Làm cách nào chúng tôi có thể khắc phục sự cố đóng trong vòng lặp?
  6. sử dụng thay vì trong các vòng lặp hoặc sử dụng (Biểu thức hàm được gọi ngay lập tức) có thể khắc phục các sự cố đóng bằng cách tạo phạm vi mới cho mỗi lần lặp.
  7. IIFE là gì?
  8. MỘT là một hàm được thực thi ngay sau khi được tạo, thường được sử dụng để tạo phạm vi mới và tránh xung đột biến.
  9. Các bao đóng có thể được sử dụng trong lập trình không đồng bộ không?
  10. Có, việc đóng là cần thiết trong lập trình không đồng bộ để duy trì trạng thái và bối cảnh trong các hoạt động không đồng bộ như lời hứa và lệnh gọi lại.
  11. Ghi nhớ là gì và việc đóng cửa giúp ích như thế nào?
  12. Ghi nhớ là một kỹ thuật tối ưu hóa để lưu trữ kết quả của các lệnh gọi hàm đắt tiền. Việc đóng giúp bằng cách duy trì quyền truy cập vào bộ nhớ đệm qua nhiều lệnh gọi hàm.
  13. Việc đóng cửa giúp xử lý sự kiện như thế nào?
  14. Các bao đóng giữ lại trạng thái của các biến mà trình xử lý sự kiện cần, đảm bảo chúng hoạt động chính xác khi sự kiện được kích hoạt.
  15. Mẫu mô-đun trong JavaScript là gì?
  16. Mẫu mô-đun sử dụng các bao đóng để tạo các biến và hàm riêng tư, đóng gói chức năng và tránh ô nhiễm phạm vi toàn cầu.
  17. Việc đóng cửa có thể mô phỏng các phương thức riêng tư trong JavaScript không?
  18. Có, các bao đóng có thể mô phỏng các phương thức riêng tư bằng cách giữ cho các biến và hàm chỉ có thể truy cập được trong phạm vi của hàm nơi chúng được xác định.

Nắm vững các bao đóng trong JavaScript, đặc biệt là trong các vòng lặp, là rất quan trọng để viết mã hiệu quả và có thể dự đoán được. Bằng cách tận dụng , , Và , nhà phát triển có thể tránh được những cạm bẫy thường gặp và đảm bảo phạm vi biến chính xác. Sự hiểu biết này nâng cao khả năng xử lý các tác vụ không đồng bộ và lập trình theo sự kiện, cuối cùng dẫn đến các ứng dụng mạnh mẽ hơn.