2009-02-26 30 views
24

Tôi có phương thức sử dụng hàm setTimeout và thực hiện cuộc gọi đến phương thức khác. Trên phương pháp tải ban đầu 2 hoạt động tốt. Tuy nhiên, sau khi hết thời gian chờ, tôi nhận được một lỗi nói rằng method2 là không xác định. Tôi làm gì sai ở đây?setTimeout và "this" trong JavaScript

ví dụ:

test.prototype.method = function() 
{ 
    //method2 returns image based on the id passed 
    this.method2('useSomeElement').src = "http://www.some.url"; 
    timeDelay = window.setTimeout(this.method, 5000); 
}; 

test.prototype.method2 = function(name) { 
    for (var i = 0; i < document.images.length; i++) { 
     if (document.images[i].id.indexOf(name) > 1) { 
      return document.images[i]; 
     } 
    } 
}; 
+0

Chỉ cần đảm bảo: là "finction" chỉ một lỗi đánh máy trong câu hỏi hoặc là nó trong mã của bạn? –

+0

hãy thêm định nghĩa và phạm vi của phương thức2 –

+0

Xin lỗi, đó là typo –

Trả lời

38

Vấn đề là setTimeout() khiến javascript sử dụng phạm vi toàn cầu. Về cơ bản, bạn đang gọi lớp method(), nhưng không phải là từ this. Thay vào đó, bạn chỉ cần nói setTimeout để sử dụng hàm method, không có phạm vi cụ thể.

Để khắc phục điều này, bạn có thể kết thúc cuộc gọi hàm trong một cuộc gọi hàm khác tham chiếu đến các biến chính xác. Nó sẽ giống như thế này:

test.protoype.method = function() 
{ 
    var that = this; 

    //method2 returns image based on the id passed 
    this.method2('useSomeElement').src = "http://www.some.url"; 

    var callMethod = function() 
    { 
     that.method(); 
    } 

    timeDelay = window.setTimeout(callMethod, 5000); 
}; 

that có thể thiscallMethod() nằm trong phạm vi phương pháp của.

Sự cố này trở nên phức tạp hơn khi bạn cần chuyển tham số sang phương thức setTimeout vì IE không hỗ trợ nhiều hơn hai tham số cho setTimeout. Trong trường hợp đó, bạn cần phải đọc lên trên closures.

Ngoài ra, dưới dạng sidenote, bạn đang thiết lập cho mình một vòng lặp vô hạn, vì method() luôn gọi method().

+0

Điều này có vẻ đáng khích lệ. Tôi sẽ thử nó và cho bạn biết –

+0

Hey, Điều này làm việc trong mozilla bu không có nghĩa là! bất kỳ đầu mối? cũng hình ảnh không lặp lại, dừng lại khi nó đạt đến hình ảnh cuối cùng –

+2

bạn là một thuật sĩ. – ihatecache

7

các this bạn sử dụng trong setTimeOut được Phạm vi thông qua chính nó. Tạo một hàm var "foo = this;" bên trong hàm t est.prototype.method và sử dụng foo để thay thế.

0

tôi nhận được một lỗi mà nói method2 là undefined

Vâng, khi bạn cắt giảm this.method từ chủ sở hữu của nó và vượt qua các chức năng một mình để setTimeout, bạn sẽ mất sự liên kết mà bộ this, vì vậy this trong method() bằng đối tượng toàn cầu window.

Xem this answer để được giải thích về cách đáng ngạc nhiên this thực sự hoạt động trong JavaScript.

39

Tùy chọn thanh lịch hơn là thêm .bind(this) vào cuối chức năng của bạn. Ví dụ:

setTimeout(function() { 
     this.foo(); 
    }.bind(this), 1000); 
// ^^^^^^^^^^^ <- fix context 

Vì vậy, câu trả lời cho câu hỏi của OP có thể là:

test.prototype.method = function() 
    { 
     //method2 returns image based on the id passed 
     this.method2('useSomeElement').src = "http://www.some.url"; 
     timeDelay = window.setTimeout(this.method.bind(this), 5000); 
     //          ^^^^^^^^^^^ <- fix context 
    }; 
+0

hình tròn có hình vuông! –

0

trong es6 bạn có thể làm điều đó như thế này

window.setTimeout(() => { 
    this.foo(); 
}, 1000); 
Các vấn đề liên quan