2010-02-03 4 views
12

Đóng cửa trong vòng lặp đang gây ra sự cố cho tôi. Tôi nghĩ rằng tôi phải thực hiện một hàm khác trả về một hàm để giải quyết vấn đề, nhưng tôi không thể làm cho nó hoạt động với mã jQuery của tôi.Đóng cửa trong vòng lặp for

Dưới đây là vấn đề cơ bản trong một hình thức đơn giản:

function foo(val) { 
    alert(val); 
} 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(function(){ 
    foo(i); 
    }); 
} 

Đương nhiên cách nhấp vào một trong ba nút sẽ đưa ra một cảnh báo nói 3. Các chức năng tôi muốn là cách bấm vào nút 1 sẽ đưa ra một cảnh báo nói 1, nút 2 sẽ nói 2, v.v.

Làm cách nào để làm điều đó?

Trả lời

10

Xem phương thức bind.

$('#button'+i).bind('click', {button: i}, function(event) { 
    foo(event.data.button); 
}); 

Từ các tài liệu:

Tham số eventData tùy chọn là không thường được sử dụng. Khi được cung cấp, đối số này cho phép chúng tôi chuyển thêm thông tin cho người xử lý. Một tiện sử dụng của tham số này là làm việc xung quanh các vấn đề gây ra bởi việc đóng cửa

+0

Cảm ơn, nó hoạt động. – Rob

+0

Làm việc cho tôi! – bychkov

+0

+1, giải quyết vấn đề của tôi quá – anvd

3

Sử dụng chức năng .each từ jquery - Tôi đoán bạn một vòng lặp thông qua các yếu tố tương tự - vì vậy thêm nhấp chuột sử dụng một cái gì đó như:

$(element).children(class).each(function(i){ 
    $(this).click(function(){ 
     foo(i); 
    }); 
}); 

Không được thử nghiệm nhưng tôi luôn sử dụng cấu trúc loại này nếu có thể.

1

Hoặc chỉ sản xuất một chức năng mới, như bạn mô tả. Nó sẽ giống như sau:

function foo(val) { 
    return function() { 
     alert(val); 
    } 
} 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(foo(i)); 
} 

Tôi chắc rằng giải pháp của Mehrdad không hoạt động. Khi bạn thấy mọi người sao chép vào một biến tạm thời, thường là để lưu giá trị của "this" có thể khác trong phạm vi con bên trong.

+0

Có giải pháp của ông đã không làm việc, tôi nghĩ rằng ông đã xóa nó. – Rob

+0

Đây là câu trả lời hay nhất mà tôi biết. Mã với ràng buộc là tốt, nhưng thông số dữ liệu đó thực sự là một hack xấu xí. Cách tiếp cận này có lợi thế là nó sẽ làm việc bất cứ lúc nào bạn gặp vấn đề này (tạo các bao đóng tham chiếu đến một biến vòng lặp), cho dù bạn có jQuery hay không. –

+0

@ Jason: trong khi tôi đồng ý đây là một câu trả lời tuyệt vời, và chắc chắn câu trả lời tôi đã đưa ra nếu jQuery không được đề cập và gắn thẻ trong câu hỏi, tôi phải không đồng ý về nó là một "xấu xí hack" - nó chắc chắn neater. Ngoài ra, 'Function.bind' bán tương tự nằm trong đặc điểm kỹ thuật ấn bản thứ 5, vì vậy bạn có thể nói câu trả lời tốt nhất cho đồng bằng ol 'js sẽ là phương pháp tạo mẫu tương đương sẽ cung cấp chức năng đó trong các phiên bản hiện tại của js. http://snipplr.com/view/13987/functionbind/ chỉ là một ví dụ tôi có thể tìm thấy, tôi biết có rất nhiều. –

5

giải pháp @Andy là đẹp nhất. Nhưng bạn cũng có thể sử dụng phạm vi Javascript để giúp bạn lưu giá trị trong phần đóng của mình.

Bạn làm như vậy bằng cách tạo phạm vi mới trong vòng lặp của bạn bằng cách thực hiện một hàm ẩn danh.

for (var i = 0; i < 3; i++) { 
    (function(){ 
    var index = i; 
    $('#button'+index).click(function(){ 
     foo(index); 
    }); 
    })(); 
} 

Vì thân vòng lặp là một phạm vi mới tại mỗi lần lặp, biến chỉ mục được nhân đôi với giá trị chính xác tại mỗi lần lặp.

+0

cảm ơn điều đó hữu ích khi biết – Rob

6

Hãy thử mã này:

function foo(val) { 
    alert(val); 
} 

var funMaker = function(k) { 
    return function() { 
    foo(k); 
    }; 
}; 

for (var i = 0; i < 3; i++) { 
    $('#button'+i).click(funMaker(i)); 
} 

Một số điểm quan trọng ở đây:

  • JavaScript là chức năng scoped. Nếu bạn muốn có một phạm vi mới ('sâu hơn'), bạn cần tạo một hàm để giữ nó.
  • Giải pháp này là Javascript cụ thể, nó hoạt động có hoặc không có jQuery.
  • Các giải pháp làm việc vì mỗi giá trị của i được sao chép trong một phạm vi mới như k, và các chức năng trở về từ funMaker đóng xung quanh k (mà không thay đổi trong vòng lặp), chứ không phải xung quanh i (mà không).
  • Mã của bạn không hoạt động vì chức năng bạn chuyển đến click không 'sở hữu' số i, mã sẽ đóng trên số i của người tạo và i thay đổi trong vòng lặp.
  • Ví dụ có thể đã được viết với funMaker được gạch chân, nhưng tôi thường sử dụng các hàm trợ giúp như vậy để làm cho mọi việc rõ ràng hơn.
  • Đối số của funMakerk, nhưng điều đó không có sự khác biệt, nó có thể là i mà không có bất kỳ vấn đề nào, vì nó tồn tại trong phạm vi chức năng funMaker.
  • Một trong những giải thích rõ ràng nhất về mô hình đánh giá 'Môi trường' được tìm thấy trong 'Cấu trúc và giải thích các chương trình máy tính', bởi Sussman & Abelson (http://mitpress.mit.edu/sicp/ toàn văn có sẵn trực tuyến, không dễ đọc) - xem phần 3.2. Vì JavaScript thực sự là Lược đồ với cú pháp C, giải thích đó là OK.

EDIT: Đã sửa một số dấu chấm câu.

+0

Giống như câu trả lời của người tối, nhưng với một số giải thích tốt đẹp. * "JavaScript thực sự là Scheme với cú pháp C" * Mỗi lần ai đó hiểu điều này lần đầu tiên, một thiên thần JS được đôi cánh của mình. –