2013-08-31 27 views
5

Tôi có nền Java và gần đây tôi đã thử nghiệm với việc thừa kế JavaScript. Tôi bắt đầu viết một số đối tượng và sau khi đọc một số ví dụ, tôi đã tìm thấy kiểu mã phù hợp nhất với tôi.Tại sao sử dụng Object.create cho mẫu thử nghiệm khi mở rộng một đối tượng?

Dưới đây là những gì tôi có:

var Class = function() {}; 
Class.extend = function(p_constructor) { 
    var Superclass = this; 
    // the following line confuses me 
    p_constructor.prototype = Object.create(Superclass.prototype); 
    p_constructor.prototype.constructor = p_constructor; 
    p_constructor.extend = Superclass.extend; 
    return p_constructor; 
}; 

Vì vậy, bây giờ khi tôi muốn xác định một đối tượng mà mở rộng loại I chỉ cần gõ:

var Person = Class.extend(function(p_firstName, p_lastName) { 
    this.firstName = p_firstName; 
    this.lastName = p_lastName; 
}); 

và sau đây sẽ là sự thật:

var p = new Person('john', 'smith'); 
p instanceof Person; // true 
p instanceof Class; // true 

Tôi chỉ gặp khó khăn khi hiểu ef là gì Sự khác biệt fective giữa các dòng sau trong Class.extend chức năng:

/* 1) */ p_constructor.prototype = new Superclass(); 
/* 2) */ p_constructor.prototype = Superclass.prototype; 
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 
/* 4) */ p_constructor.prototype = Object.create(Superclass); 

tôi nhận ra rằng việc sử dụng dòng 1 không phải là rất khôn ngoan nếu một số siêu constructors ném lỗi, nhưng chính xác sự khác biệt giữa các dòng 2, 3 và 4 là gì?

Trả lời

6

Để trả lời câu hỏi của riêng tôi:

/* 1) */ p_constructor.prototype = new Superclass(); 

Như tôi đã nói, nó không phải là rất khôn ngoan để sử dụng này vì nó thực sự tạo ra các đối tượng toàn bộ lớp cha. Toàn bộ điểm thừa kế prototypal là chia sẻ các đối tượng nguyên mẫu để các định nghĩa chức năng dự phòng (và đôi khi đối tượng) có thể tránh được.

/* 2) */ p_constructor.prototype = Superclass.prototype; 

Điều này sẽ ổn nếu bạn có thể chắc chắn nguyên mẫu của nhà xây dựng sẽ không bao giờ được sửa đổi bởi bên thứ ba. Giả sử ai đó sử dụng lớp của bạn muốn thêm chức năng bổ sung vào nguyên mẫu của nó. Việc thay đổi nguyên mẫu của p_constructor sẽ trực tiếp ảnh hưởng đến nguyên mẫu của lớp cha và có thể đưa ra các lỗi trong hành vi của siêu lớp. Vì vậy, các dòng tiếp theo của mã được sử dụng thay vì:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 

Điều này tạo ra một đối tượng mới (chẳng hạn) mà nguyên mẫu (thực sự biến __proto__) được thiết lập để nguyên mẫu lớp cha. Bất kỳ thay đổi nào đối với p_constructor.prototype hiện giờ không làm thay đổi hành vi của Superclass.

/* 4) */ p_constructor.prototype = Object.create(Superclass); 

Dòng trên hoạt động, nhưng không có ý nghĩa bởi vì nó chỉ đặt nguyên mẫu cho hàm tạo Superclass.

Ngoài ra, các dòng sau đã gây nhầm lẫn đối với tôi cũng như:

p_constructor.prototype.constructor = p_constructor; 

Nó làm cho không có sự khác biệt trong hành vi của p_constructor, nó chỉ làm cho các tham chiếu đến các nhà xây dựng sẵn trong đối tượng cụ thể. Một lừa gọn gàng là thêm lớp cha để nguyên mẫu cũng như:

p_constructor.prototype.superclass = Superclass; 

Và sau đó các đoạn mã sau đây sẽ làm việc:

function Constructor(p_params) { 
    // call constructor of the superclass 
    this.superclass(p_params); 
} 
+0

mát mà bạn đã trả lời câu hỏi của bạn ở đây.Trong khối mã cuối cùng của bạn, hãy xem xét ngữ cảnh của hàm tạo hàm của lớp cha khi bạn gọi nó theo cách này; Tôi nghĩ rằng những gì bạn muốn làm là 'this.superclass.apply (this, arguments);' - sau đó, nếu hàm tạo của super đi 'this.sumthin = ...', giá trị được gắn vào cá thể của lớp con. – dalgard

+0

Các giá trị từ superclass sẽ được gắn vào instance hiện tại của phân lớp, bởi vì nó được gọi từ 'this', do đó, context của nó sẽ thực sự là cùng một instance mới của subclass. – jeremija

+0

Ồ, bạn nói đúng. Tôi nghĩ rằng tôi thấy mô hình này để truy cập vào siêu thường xuyên hơn: 'subclass.prototype.super = superclass.prototype' (có thể với việc bổ sung' subclass.super = superclass'). Có thể bạn sẽ muốn xem [giải pháp của tôi] (https://gist.github.com/dalgard/9169923) cho những điều này (xem ví dụ trong phần bình luận). – dalgard

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