2012-09-06 24 views
11

Tôi đang cố gắng để có một đối tượng javascript chạy một phương thức trì hoãn và khi nó là .done() gọi một hàm trong cùng một đối tượng đó. Tôi đang gặp vấn đề bởi vì "điều này" trở thành đối tượng trì hoãn thay vì đối tượng gọi nó.Thay đổi được hoãn lại của JQuery "this"

PageObject.prototype.successFunction = function() { 
    console.log(arguments); 
    return console.log(this.name + " Success function called"); 
}; 

PageObject.prototype.loadPage = function(url) { 
    return $.when($.mobile.loadPage("pages/" + url)) 
    .done(this.successFunction); 
}; 

var pg = new PageObject(); 
pg.loadPage("test.html"); 

Làm cách nào để gửi "điều này" vào successFunction? PageObject này sẽ được mở rộng bởi những người khác, vì vậy biết "điều này" khi chạy successFunction sẽ rất tiện dụng.

Có vẻ như đơn giản và có thể có câu trả lời đơn giản. Tôi đã nhìn vào .apply() nhưng tôi không chắc chắn nó đã giúp. Bài đăng trên tràn ngăn xếp này hữu ích một chút, nhưng nó đã phá vỡ phút tôi đặt nó vào hàm .done().

Functions as parameters (with parameters) -- JavaScript

+1

FWIW, đối tượng trì hoãn không thay đổi điều này, nó chỉ hoạt động như thế nào. Giá trị của điều này không được xác định bằng cách/nơi một hàm được định nghĩa, nhưng nó được gọi như thế nào. –

Trả lời

14

jQuery proxy sẽ trả về hàm ràng buộc vào một bối cảnh cụ thể:

PageObject.prototype.loadPage = function(url) { 
    return $.when($.mobile.loadPage("pages/" + url)) 
    .done($.proxy(this.successFunction, this)); 
}; 

Ngoài ra còn có ES5 của bind mà hoạt động tương tự nhưng cần được shimmed trong trình duyệt cũ

PageObject.prototype.loadPage = function(url) { 
    return $.when($.mobile.loadPage("pages/" + url)) 
    .done(this.successFunction.bind(this)); 
}; 

applycall có thể thực hiện một hàm immediatel y với ngữ cảnh được chỉ định, nhưng proxybind trả về một hàm có thể được sử dụng sau hoặc được truyền cho các chức năng khác.

+0

Câu trả lời tuyệt vời, đây chính xác là những gì tôi cần (và tôi đã phát điên khi cố gắng tìm ra nó). Tôi đã sử dụng phiên bản $ .proxy mà bạn đã đăng. Cảm ơn! – Chris

2

this "biến" trong JavaScript được gọi là "đối tượng gọi" và được xác định khi hàm kèm theo của nó được gọi (không phải khi được xác định). Nó có thể được thiết lập một vài cách khác nhau:

  1. Bạn có thể đặt nó bằng cách sử dụng các . điều hành (ví dụ myObject.myFunction())
  2. Bạn có thể đặt nó bằng cách sử dụng một chức năng call() hoặc apply() phương pháp
  3. Bạn có thể (dưới ES5) ràng buộc vĩnh viễn bằng cách sử dụng phương pháp bind() của chức năng
  4. nó sẽ mặc định đối tượng toàn cầu nếu không ai trong số các phương pháp trên đặt nó là cái gì khác

Điều quan trọng cần hiểu là (ngoài phương pháp 3 ở trên), đó là tất cả về cách hàm được gọi khi nó được gọi, không phải cách nó được tham chiếu, không phải cách nó được lưu trữ, không phải nơi nó được tạo.

Trong trường hợp của bạn, bạn đang chuyển this.successFunction làm tham chiếu hàm được gọi bởi jQuery, nhưng nó không gọi nó theo cách đó (vì nó chỉ có tham chiếu đến hàm, chứ không phải bất kỳ thông tin nào về hàm đó nên được gọi).

Có một vài thủ thuật lạ mắt, bạn có thể sử dụng với .bind() phương pháp jQuery $.proxy() hoặc ES5, nhưng khi nó đi xuống đến nó, cách đơn giản nhất để xử lý nó chỉ đơn giản là giữ lại this qua một biến đóng-chỉnh phạm vi và sử dụng một chức năng wrapper:

PageObject.prototype.loadPage = function(url) { 
    var self = this; 
    return $.when($.mobile.loadPage("pages/" + url)) 
      .done(function() { self.successFunction(); }); 
}; 

Lưu ý rằng chúng tôi đang sử dụng phương pháp 1 để ràng buộc một cách rõ ràng successFunction 's gọi đối tượng để được giống như đối tượng gọi loadPage của.Nó ngắn gọn, đơn giản, rõ ràng, hoạt động tốt theo ES3, và không phụ thuộc vào jQuery.

+0

+1 cho những gì xảy ra đằng sau hậu trường, nhưng tôi có xu hướng thích các thủ thuật ưa thích, nếu có, vì nó giữ cho trình dọn dẹp mã. – Dennis

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