2010-06-24 44 views
9

Tôi đang chạy vào các vấn đề sau đây mà đã thực sự đã cho tôi bối rối:Gọi hàm thành viên từ javascript constructor

Tôi có

function SystemList(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 

Khi tôi cố gắng và chạy này, tôi nhận được lỗi sau: của router TypeError: Object # không có phương thức 'refreshData' trong hàm tạo.

Bất kỳ ai có ý tưởng tại sao điều này không thành công? Để mắt của tôi có vẻ như nó sẽ được làm việc.

Edit:

Ví dụ về cách tôi tạo ra một ví dụ:

function UserMiniProfile(UID) 
{ 
    this.UID = UID; 
    this.systemList = new SystemList(this.UID); 
    this.htmlID = 'user-'+this.UID+'-profile'; 
} 
+0

Đã thêm ví dụ về cách tôi tạo obj. – nazbot

+1

Bạn có chắc chắn rằng bạn đang sử dụng hàm tạo 'SystemList' * sau khi * tăng thêm số nguyên mẫu của nó không ?? – CMS

+0

hoạt động cho tôi: http://jsbin.com/ebasa/edit – nickf

Trả lời

13

Tôi nghĩ có lẽ bạn đang chạy vào vấn đề này về cách thức và thời điểm khai báo hàm so với mã từng bước (những gì mà mã thông báo gọi là mã số ) xảy ra.

Mã như thế này sẽ thất bại theo cách bạn mô tả, ví dụ:

var obj = new Thingy("Fred"); 

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

... bởi vì bạn đang gọi các nhà xây dựng trước khi thêm setName chức năng để nguyên mẫu. Lưu ý rằng việc gọi hàm tạo trước khi khai báo của nó là tốt, chỉ vì hàm tạo đang sử dụng hàm được thiết lập sau bằng mã lệnh có vấn đề. Thứ tự mà trình thông dịch JavaScript sẽ cố xử lý mã đó là:

  1. Tạo chức năng Thingy và làm cho nó khả dụng trong phạm vi.
  2. Thực hiện đường dây var obj = ...., gọi hàm tạo.
  3. Thực thi mã của nhà xây dựng (trong trường hợp này ném ngoại lệ vì không có hàm this.setName).
  4. Thực hiện đường dây Thingy.prototype.setName = .... (Nếu không có trường hợp ngoại lệ nào được ném vào bước cuối cùng, tức là.)

Các bước này xảy ra cho mỗi khối tập lệnh (đầu tiên khai báo chức năng được thực hiện, sau đó mã lệnh được thực hiện theo thứ tự), và mặc dù ví dụ trên là khá rõ ràng, khi bạn bắt đầu tập hợp các phần từ nhiều vị trí khác nhau, bạn có thể tạo tình huống này ít rõ ràng hơn.

Các giải pháp, rõ ràng, là để đảm bảo bạn không xây dựng các đối tượng trước khi bạn đã thiết lập setName tài sản:

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

var obj = new Thingy("Fred"); 

... và một lần nữa, phía trên là khá rõ ràng, nhưng có thể tạo ra những tình huống này thay vì ít rõ ràng hơn trong thế giới thực.

Nghi ngờ của tôi là đây là những gì đang xảy ra trong trường hợp của bạn. Thật dễ dàng để chứng minh: Sử dụng trình gỡ lỗi như Firebug trên Firefox, VS.Net hoặc Trình gỡ lỗi tập lệnh cho IE, DevTools của Chrome, v.v., đặt điểm ngắt trên đường dây SystemList.prototype.refreshData = ... và điểm ngắt trên đường mà bạn đang thực hiện new SystemList(...) và xem điểm nào thực hiện trước.

Dưới đây là một vài câu đố thể hiện sự cố: This one không thành công trong hàm tạo, this one succeeeds.

+0

Xin lỗi vì sự chậm trễ, có, đây là vấn đề. Tôi di chuyển mọi thứ xung quanh và nó hoạt động ngay bây giờ. – nazbot

+0

@nazbot: Ah, tốt, rất vui vì điều đó! –

0

Bạn cần phải gán lớp học của bạn đầu tiên:

SystemList = function(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 
+0

Thật sao? Tôi chưa bao giờ thấy cách này để chỉ định một lớp js. – nazbot

+2

Không, thay đổi nó từ 'hàm SystemList (UID)' thành 'SystemList = function (UID)' không liên quan gì đến nó. Tất cả những gì nó làm là thay đổi nó từ một hàm được đặt tên thành một hàm ẩn danh. –

+3

(Trích dẫn chính mình) * "Tất cả những gì nó làm là thay đổi nó từ một hàm được đặt tên thành một hàm ẩn danh." * Thực ra, đó không phải là * tất cả * nó. Nó cũng thay đổi nó từ một hàm * khai báo * thành một hàm * biểu thức *, điều này sẽ xảy ra sau. Nếu tôi đúng về những gì đang xảy ra với mã OP, kết quả có khả năng của thay đổi này sẽ là thay vì constructor thất bại, cuộc gọi * tới constructor sẽ thất bại vì 'SystemList' sẽ không được xác định. Không giải quyết vấn đề bằng cách nào, nhưng tuyên bố trước đó của tôi là không đầy đủ, vì vậy tôi nghĩ rằng tôi nên gắn cờ đó lên. –

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