2013-03-07 3 views
7

Các đối tượng JavaScript có thành viên 'nguyên mẫu' để tạo điều kiện kế thừa. Nhưng có vẻ như, chúng ta có thể sống hoàn toàn tốt, ngay cả khi không có nó, và tôi tự hỏi, những lợi ích của việc sử dụng nó là gì. Tôi tự hỏi những ưu và nhược điểm là gì.Tại sao nên sử dụng 'nguyên mẫu' cho kế thừa javascript?

Ví dụ, hãy xem xét những điều sau đây (ở đây jsfiddle):

function Base (name) { 

    this.name = name; 
    this.modules = []; 
    return this; 
} 

Base.prototype = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule"); 
    } 
}; 

function Derived(name) { 
     Base.call(this,name); // call base constructor with Derived context 
} 

Derived.prototype = Object.create(Base.prototype); 

Derived.prototype.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.prototype.initModule.call(this); 
    } 

var derived = new Derived("dname"); 
console.log(derived.name); 
derived.initModule(); 

Một câu hỏi là, tại sao sử dụng 'mẫu' ở tất cả? Chúng tôi cũng có thể làm điều gì đó như Derived = Object.create(Base);

ví dụ (jsfiddle):

Base = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule",this.name); 
    }, 
    init: function(name) { 
     this.name = name; 
     this.modules = []; 
    } 
}; 

Derived = Object.create(Base); 

Derived.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.initModule.call(this); 
    } 
Derived.init("dname"); 
console.log(Derived.name); 
Derived.initModule(); 
+3

Một chuyên gia là tốc độ: http://jsperf.com/prototype-vs-non-prototype/11 – StuR

+0

nếu bạn có 4 cấp độ thừa kế? bạn sẽ khai báo một phương thức newnewnewInitModule? – mpm

+0

@mpm bạn đúng, là một sai lầm, tôi chỉnh sửa này đi – Lior

Trả lời

3

Nếu bạn không sử dụng mẫu thử nghiệm, các phương pháp được định nghĩa lại với mọi lớp. Tức là, new Base; new Base; new Base sẽ tạo các hàm sáu trong ví dụ thứ hai. Điều này cần nhiều thời gian và không gian hơn. Derived cũng sẽ tạo các chức năng riêng của nó. Ngoài ra, bạn không thể sử dụng nguyên mẫu để thay đổi phương pháp cho từng cá thể đang bay (hoặc thêm các phương thức mới), có thể hữu ích - đặc biệt là trên các mô-đun.

Tuy nhiên đó không phải là để nói rằng bạn nên luôn luôn sử dụng nguyên mẫu cho mọi phương pháp. Mỗi tình huống là khác nhau.

prototype cũng cho phép bạn gọi các phương thức trong ngữ cảnh khác mà không cần tạo cá thể (như trong trường hợp Array.prototype.forEach.call trên đối tượng giống như mảng).

+0

cảm ơn! hiệu suất dường như là vấn đề chính. Nhưng bạn có thể xây dựng trên 'bạn không thể sử dụng nguyên mẫu để thay đổi phương pháp cho mỗi trường hợp trên bay'? không chắc chắn tôi hiểu được – Lior

+0

@ Ý tôi là nếu bạn định nghĩa phương thức 'Base.init', bạn không thể ghi đè nó bằng' Base.prototype.init' (bao gồm bất kỳ "con" nào của nó). Nó sẽ sử dụng phương thức 'Base.init' mà ban đầu bạn đã định nghĩa trừ khi bạn gọi một cách rõ ràng từ chuỗi nguyên mẫu –

1

Về cơ bản nó là khá đơn giản, The Object.create là một phần của ECMAScript 5, mà còn khá mới mẻ. Prototype đã được khoảng từ đầu javascript và được hỗ trợ bởi tất cả các trình duyệt.

Vì vậy, miễn là bạn cần hỗ trợ cho Internet Explorer 7 hoặc 8, bạn không nên dựa vào Tạo. Xem thêm https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create

(điều này cũng cho thấy một polyfill, trong đó sử dụng nguyên mẫu ;-))

-2

Bạn không cần phải nguyên mẫu (mà IMHO là một con) cho OO.

Xem xét việc này cho thừa kế:

function SubClass() 
{ 
    var object = {}; 
    object.publicVar = 2; 
    object.publicMethod = function SubClassPubMeth() 
     { 
     return this.publicVar + 2; 
     }; 
    object.poly = function SubClassPoly() 
     { 
     return 'SubClassPoly'; 
     }; 
    return object; 
} 

function Class() 
{ 
    var object = new SubClass(); 
    object.classPublicVar = 3; 
    object.classPublicMethod = 
     function ClassMethod() 
     { 
      return this.publicVar + this.classPublicVar; 
     }; 
    object.poly = function ClassPoly() 
     { 
     return 'ClassPoly'; 
     }; 
    return object; 
} 

vẻ để phù hợp với các hóa đơn cho thừa kế.

Cũng xem xét việc này cho ẩn thông tin:

chức năng Class() { var đối tượng = {}; object.x = 3; var privateVar = 3; function privateFunction (đối tượng) { trả về đối tượng.x + privateVar; }

object.publicFunction = function() 
    { 
    var priv = privateFunction(this); 
    priv += privateVar; 
    privateVar = privateVar + 3; 
    return priv; 
    }; 
return object; 

}

Cũng dường như làm các trick để biết thông tin ẩn (AKA đóng gói)

Tôi cần phải nói nhiều.

+0

Nếu bạn quan tâm về buổi biểu diễn sau đó bạn cần nguyên mẫu khi bạn đang subclassing, hoặc bất cứ khi nào bạn đang tạo trường hợp mới của cùng một đối tượng. – mpm

+0

Những thứ bạn làm với Javascript không yêu cầu nhiều sức mạnh xử lý. Nếu bạn quan tâm thì bạn viết mã bằng Java (ví dụ). –