2011-02-07 23 views
6

Tôi gặp sự cố với những gì trình duyệt xem là 'this'. Trong ví dụ sau, gọi pingMe() trên abc sẽ đợi 1 giây và sau đó trình duyệt sẽ nói rằng Object DOMWindow không có phương thức 'func'. Thay vì giải quyết 'this' thành thể hiện của lớp ABC (abc), nó thay vào đó giải quyết thành DOMWindow, như thể đối tượng không liên quan. Tôi rõ ràng không hiểu cách setTimeout hoạt động liên quan đến phạm vi gọi lại. Bất kỳ đề xuất làm thế nào tôi có thể thực hiện cuộc gọi lại này thành công?Bộ đếm giờ Coffeescript và con trỏ 'this' này trên gọi lại

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout(doPing, 1000) 

    doPing = -> 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 
+1

hm, thay đổi dòng setTimeout thành 'obj = this; setTimeout ((-> obj.doPing()), 1000) 'và khai báo doPing tới' doPing: -> 'dường như sửa chữa nó. Dường như CoffeeScript giữ hành vi JavaScript thông thường trong các trường hợp này. – Larry

Trả lời

10

Tôi nhận mã này hoạt động.

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout => 
    @doPing() 
    , 1000 

    doPing: -> 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 

phương pháp doping của bạn đã được xác định doPing = ->, trong khi những người khác đều sử dụng name: ->, tôi đã thay đổi nó theo cách đó. pingMe sử dụng => để tạo hàm chưa đặt tên và @doPing để liên kết this với hàm.

Không chắc chắn nếu điều này là chính xác, tôi hiếm khi sử dụng JavaScript. Nhưng tôi hy vọng nó có thể cung cấp cho bạn một hướng để nhìn xa hơn.

+0

Đúng vậy. kiến thức của tôi về '=>' đã thiếu. – Larry

0

Có lẽ để rõ ràng hơn một chút, bạn có thể ràng buộc phương thức "doPing" thay thế. Nó sẽ trông sạch hơn một chút và FWIW, tôi nghĩ nó thể hiện rõ hơn những gì bạn đang tìm kiếm để đạt được.

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout => @doPing, 1000 

    doPing: => 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 
+0

Tôi tin rằng phải là '=> @doPing()'. '=> @ doPing' đánh giá một hàm trả về hàm bị ràng buộc, không phải hàm nào gọi hàm bị ràng buộc. Xem câu trả lời của Reiner. – joeytwiddle

1

Một giải pháp thay thế đó là gần gũi hơn với những gì bạn sẽ làm trong ES5 là:

pingMe: -> 
    setTimeout(@doPing.bind(@), 1000) 

hoặc nếu bạn muốn tiết kiệm ngoặc:

pingMe: -> 
    setTimeout (@doPing.bind @), 1000 

Lưu ý rằng bind là ES5, do đó chỉ available trong IE từ phiên bản 9.


Cũng lưu ý, bạn nên bằng mọi giá tránh sự cám dỗ để thử:

setTimeout(@doPing.bind @, 1000) # BAD! 
     or 
    setTimeout @doPing.bind @, 1000  # BAD! 

vì cả hai trong những vượt qua số như là đối số thứ hai để bind, không setTimeout!

Các vấn đề liên quan