JavaScript đóng bên trong các vòng lặp - ví dụ thực tế đơn giản

  • 2/6/2020 6:28:33 AM bởi admin
  • 0 câu trả lời

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

Chạy đoạn mãMở rộng đoạn trích Nó xuất ra điều này:

Giá trị của tôi: 3 Giá trị của tôi: 3 Giá trị của tôi: 3

Trong khi tôi muốn nó xuất ra:

Giá trị của tôi: 0 Giá trị của tôi: 1 Giá trị của tôi: 2

Vấn đề tương tự xảy ra khi sự chậm trễ trong việc chạy chức năng là do sử dụng trình lắng nghe sự kiện:


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

Chạy đoạn mãMở rộng đoạn trích Mã hoặc mã không đồng bộ, ví dụ: sử dụng Promise:

// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for (var i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
}

Chạy đoạn mãMở rộng đoạn trích Giải pháp cho vấn đề cơ bản này là gì?

1 câu trả lời, 0 Đã được chấp nhận

admin posted 2/6/2020 6:29:14 AM

Vấn đề là biến đó i, trong mỗi hàm ẩn danh của bạn, bị ràng buộc với cùng một biến bên ngoài hàm.

Giải pháp cổ điển: Đóng cửa Những gì bạn muốn làm là liên kết biến trong mỗi hàm với một giá trị riêng, không thay đổi bên ngoài hàm:


var funcs = [];

function createfunc(i) {
  return function() {
    console.log("My value: " + i);
  };
}

for (var i = 0; i < 3; i++) {
  funcs[i] = createfunc(i);
}

for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

Chạy đoạn mãMở rộng đoạn trích Vì không có phạm vi khối trong JavaScript - chỉ có phạm vi chức năng - bằng cách gói việc tạo hàm trong một hàm mới, bạn đảm bảo rằng giá trị của "i" vẫn như bạn dự định.

Giải pháp 2015: forEach Với tính khả dụng tương đối rộng rãi của Array.prototype.forEachhàm (năm 2015), đáng chú ý là trong các tình huống liên quan đến phép lặp chủ yếu trên một mảng các giá trị, .forEach()cung cấp một cách rõ ràng, tự nhiên để có được sự đóng cửa riêng biệt cho mỗi lần lặp. Đó là, giả sử bạn đã có một số loại mảng chứa các giá trị (tham chiếu DOM, đối tượng, bất cứ thứ gì) và vấn đề phát sinh khi thiết lập các cuộc gọi lại cụ thể cho từng thành phần, bạn có thể thực hiện việc này:


var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
  // ... code code code for this one element
  someAsynchronousFunction(arrayElement, function() {
    arrayElement.doSomething();
  });
});

Ý tưởng là mỗi lời gọi của hàm gọi lại được sử dụng với .forEachvòng lặp sẽ được đóng lại riêng. Tham số được truyền vào trình xử lý đó là phần tử mảng cụ thể cho bước lặp cụ thể đó. Nếu nó được sử dụng trong một cuộc gọi lại không đồng bộ, nó sẽ không va chạm với bất kỳ cuộc gọi lại nào khác được thiết lập ở các bước khác của lần lặp.

Nếu bạn tình cờ làm việc trong jQuery, $.each()hàm này cung cấp cho bạn một khả năng tương tự.

Giải pháp ES6: let ECMAScript 6 (ES6) giới thiệu các từ khóa mới letvà constcác từ khóa có phạm vi khác với varcác biến dựa trên. Ví dụ: trong một vòng lặp có letchỉ mục dựa trên cơ sở, mỗi lần lặp qua vòng lặp sẽ có một giá trị mới trong iđó mỗi giá trị nằm trong phạm vi vòng lặp, do đó mã của bạn sẽ hoạt động như bạn mong đợi. Có rất nhiều tài nguyên, nhưng tôi muốn giới thiệu bài đăng khối của 2ality như một nguồn thông tin tuyệt vời.

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    console.log("My value: " + i);
  };
}

Mặc dù vậy, hãy cẩn thận, IE9-IE11 và Edge trước khi hỗ trợ Edge 14 letnhưng lại bị lỗi ở trên (chúng không tạo mới imỗi lần, vì vậy tất cả các chức năng trên sẽ đăng nhập 3 như chúng ta sẽ sử dụng var). Edge 14 cuối cùng đã làm cho nó đúng.

Có câu trả lời không? Đăng nhập hoặc là Đăng ký để gửi câu trả lời của bạn
câu trả lời của bạn
Hủy bỏ
Chi tiết
  • Đăng 2/6/2020 6:28:33 AM
  • 1 lượt xem, 0 replies