2012-05-13 33 views
6

Tôi muốn chuyển đối số cho hàm được gọi là sử dụng setTimeout. Tôi đã tìm thấy ba tùy chọn:Làm thế nào tôi có thể chuyển một đối số cho một hàm được gọi là sử dụng setTimeout?

A = 1; 
// Method 1: closure things 
setTimeout(function() { whatsA(A); }, 100); 
// Method 2: third argument (same result with [A]) 
setTimeout(whatsA, 100, A); 
// Method 3: eval 
setTimeout('whatsA(' + A + ')', 100); 
A = 2; 
function whatsA(X) { console.log(X); } 

Điều này cho thấy 2, undefined1 trong Internet Explorer 9.

Phương pháp 1: Rõ ràng, tôi không muốn tranh luận phải được thay đổi sau khi đi qua nó (chắc chắn trong trường hợp các số nguyên đơn giản).

Phương pháp 2: Điều này sẽ hoàn hảo nếu chỉ Internet Explorer hỗ trợ.

Phương pháp 3: Đây có vẻ là lựa chọn duy nhất. Nhưng nó có vẻ khá kém so với những người khác, đi qua một cái gì đó để được đánh giá chứ không phải là một chức năng.

Có cách nào tốt hơn không?

+2

Phương pháp 3 là một trong những bạn nên **không bao giờ sử dụng. Và Phương pháp 2 không được chấp nhận ngay cả trong các trình duyệt tắc kè - vì vậy ngay cả khi không hỗ trợ IE, nó cũng khá là không có. – ThiefMaster

Trả lời

7

Giải pháp tốt nhất mà tôi có thể nghĩ đến là sử dụng bind():

A = 1; 
setTimeout(whatsA.bind(this, A), 100); 

bind() thực sự là một chức năng gọi, nó đọc giá trị hiện tại A và trả về một chức năng với giá trị đó bị ràng buộc như một cuộc tranh cãi. Nếu bạn cảm thấy khó hiểu, hãy thử này:

var newFun = whatsA.bind(this, 42); 
newFun() 

Lưu ý rằng this là loại một lời nói dối ở đây - bạn có thể an toàn vượt qua window là tốt.


Phương pháp đầu tiên cũng là chấp nhận được, nó chỉ cần được cải thiện đôi chút:

A = 1; 
var tmpA = A; 
setTimeout(function() { whatsA(tmpA); }, 100); 

gì bạn đang quan sát thực sự là một tính năng, không phải là một lỗi. Bạn đang đi qua một đóng cửa để setTimeout() tham chiếu biến cục bộ. JavaScript đủ thông minh để trì hoãn quyền truy cập vào biến đó đến thời điểm hàm thực sự được gọi. Và vì bạn đã sửa đổi biến, bạn sẽ thấy phiên bản mới nhất.


Phương pháp thứ hai không được dùng nữa sẽ không hoạt động trong bất kỳ trình duyệt nào.


Phương pháp thứ ba là khủng khiếp, tránh chuyển chuỗi đến setTimeout(), luôn có giải pháp tốt hơn.

+0

Ngoài ra còn có các giải pháp 'whatsA.apply (this, [A])' và 'whatsA.call (này, A)'. – VisioN

+0

+1 cho giải pháp '.bind()' sạch. @VisionN: Các phiên bản đó sẽ yêu cầu chức năng tự gọi để tránh đóng trên biến mặc dù. – ThiefMaster

+0

* bạn có thể an toàn vượt qua cửa sổ cũng như * - hoặc 'null' là IMHO sạch hơn. – ThiefMaster

4

Bạn có thể sử dụng đóng cửa:

setTimeout((function(A){ 
       return function(){ 
        whatsA(A); 
       }; 
      })(A), 100); 
+0

+1 Ý tưởng tuyệt vời! – VisioN

0

Trong ba phương pháp của bạn:

Lựa chọn 1:

setTimeout(function() { whatsA(A); }, 100);

một này hoạt động ở khắp mọi nơi và rất đơn giản.Đó là những gì tôi muốn giới thiệu trừ khi biến A có thể thay đổi trước khi hàm setTimeout được gọi. Nếu bạn cần đóng băng giá trị của A, thì hãy xem tùy chọn 4 của tôi bên dưới.


Phương án 2:

setTimeout(whatsA, 100, A);

này chỉ hoạt động trong một số trình duyệt. Không được khuyến khích.


Lựa chọn 3:

setTimeout('whatsA(' + A + ')', 100);

này không bao giờ được khuyến khích. Xây dựng mã như một chuỗi và sau đó đánh giá nó sau này là hầu như không bao giờ là giải pháp tốt nhất.


Tôi muốn giới thiệu Lựa chọn 4:

Để đóng băng giá trị của A, bạn có thể tạo ra một kết thúc sử dụng một thực hiện chức năng tự:

A = 1; 

function(A) { 
    setTimeout(function() {whatsA(A);}, 100); 
}(A); 

A = 2; 
function whatsA(X) { console.log(X); } 
Các vấn đề liên quan