2010-08-28 37 views
5

Trong JavaScript, điều tương tự bạn có thể thực hiện theo nhiều cách khác nhau.Nguyên mẫu trong JavaScript

Hãy xem xét các ví dụ:

1:

function Circle(radius) { 
return { 
    "r" : radius, 
    "area" : function(){ 
    return Circle.pi * this.r * this.r; 
    } 
} 
} 
Circle.pi = 3.14159; 

var a = Circle(10); 
alert(a.area()); 

2:

function Circle(radius) { 
    this.r = radius; 
} 

Circle.pi = 3.14159; 
Circle.prototype.area = function(){ 
return Circle.pi * this.r * this.r; 
} 

var a = new Circle(10); 
alert(a.area()); 

Thứ hai là tốt hơn so với lần đầu tiên bởi vì chúng tôi không xác định chức năng tương tự khu vực cho bất kỳ trường hợp số Vòng kết nối.

Nhưng cho phép xem xét 3:

function Circle(radius) { 
return { 
    "r" : radius, 
    "area" : Circle.area 
} 
} 
Circle.pi = 3.14159; 
Circle.area = function(){ 
return Circle.pi * this.r * this.r; 
} 

var a = Circle(10); 
alert(a.area()); 

Có lý do nào để thích phong cách thứ hai thay vì thứ ba? Hay tôi hiểu lầm gì đó?

+0

Bạn biết về tính khả dụng của ['Math.PI'] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Math/PI), phải không? –

+1

có thể trùng lặp của [Object hướng javascript với nguyên mẫu vs đóng cửa] (http://stackoverflow.com/questions/3564238/object-oriented-javascript-with-prototypes-vs-closures) –

+0

Tôi đã thực hiện một số tiêu chuẩn như ở đây http : //blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx. Kết quả - phong cách thứ 3 chỉ giữa 1 và 2 :) Thx cho tất cả các câu trả lời và nhận xét, tôi đã học được rất nhiều. – Dan

Trả lời

4

Tôi chắc chắn sẽ đi với ví dụ 2. Cả ví dụ 1 hoặc 3 tận dụng tốt các tính năng hướng đối tượng JavaScript vì:

  1. Bạn lặp lại định nghĩa phương pháp trong mỗi trường hợp.
  2. Bằng cách trả lại một đối tượng mới thay vì sử dụng this, bạn mất danh tính của lớp học, tức là bạn không thể thực hiện kiểm tra như a instanceof Circle nữa.
  3. Bạn từ bỏ khả năng thừa kế vì bạn không sử dụng nguyên mẫu.
1

Sự khác biệt giữa Circle.prototype.areaCircle.area là chỉ có thể truy cập được bằng một phiên bản của lớp học.

Circle.prototype.area = function(){}; 
Circle.area // wrong 
(new Circle()).area // ok (you need a Circle object) 

Circle.area = function(){}; 
Circle.area // ok (you don't need the object, its static) 
(new Circle()).area // wrong 
+0

Bạn đã đọc ví dụ thứ 3 của OP chưa? –

+1

Không hoàn toàn đúng. Sau đây là hợp pháp: 'Circle.prototype.area()' (mặc dù bạn có thể muốn sử dụng 'call' hoặc' apply' với nó.) –

+0

Đúng, nhưng nếu nó trên nguyên mẫu thường thì không nên gọi như vậy, nó có thể phụ thuộc vào một số thuộc tính của cá thể. Dù sao cho điểm đó. – BrunoLM

0

Vấn đề với ví dụ 2 là, khi bạn vô tình quên sử dụng toán tử new khi tạo đối tượng, và chỉ cần gọi var a = Circle(10); (mà là tốt cho ví dụ 3, nhưng không cho thứ 2), sau đó xây dựng của bạn tạo ra rắc rối lớn:

this.r = radius; 

vì bạn đã không sử dụng new, this sẽ được gán đối tượng chung, vì vậy hàm tạo thực sự đặt biến toàn cầu r!

Vì vậy, tôi mạnh mẽ muốn dụ 3.

2

Có lý do nào để thích phong cách thứ hai thay vì thứ ba?

Phong cách thứ ba vẫn còn lãng phí một lượng nhỏ không gian để lưu trữ các mối liên hệ giữa tên area và chức năng khu vực.

Cũng bởi vì bạn đang trả lại Object mới từ {...} chữ, instanceof Circle sẽ không hoạt động.

Thứ hai tốt hơn trước vì chúng tôi không xác định cùng một vùng chức năng cho bất kỳ phiên bản nào của Vòng kết nối.

Trên thực tế, nhưng nó có thể đôi khi có ích để xác định một bản sao mới của mỗi phương pháp-một bản sao mà, nhờ đóng cửa, có thể biết được những gì đối tượng nó là ràng buộc để. Với việc tạo mẫu truyền thống, bạn chỉ nhận được ngữ cảnh this được thiết lập từ đối tượng người gọi đã truy lục nó, thay vì bị ràng buộc với một đối tượng cụ thể.Cách đầu tiên tránh được các vấn đề của this -trả lời trong những thứ như xử lý sự kiện, với mức giá của một số mất hiệu quả.

0

Tôi muốn nhận xét về "Câu hỏi thứ hai tốt hơn lần đầu vì chúng tôi không xác định cùng một vùng chức năng cho bất kỳ trường hợp nào của Vòng kết nối". Trong thực tế, điều này có thể là một lợi thế cẩu thả như là hoàn toàn không đáng kể. Tôi có xu hướng ưu tiên mã cú pháp và mã thân thiện với con người qua hiệu quả, trừ khi hiệu suất bị ảnh hưởng đáng kể. Tôi đã hoàn toàn bỏ qua tính năng Prototype của javascript và cũng tránh việc sử dụng "này", về cơ bản sử dụng kỹ thuật số 1. Nó làm việc tốt cho tôi. Tôi thấy tránh "điều này" ngăn cản rất nhiều sự nhầm lẫn về những gì "này" đề cập đến. Nó hoàn toàn có thể tạo ra các cấu trúc kiểu thừa kế mà không có "nguyên mẫu". Bạn đơn giản tạo một đối tượng siêu lớp và ghi đè bất kỳ phương thức nào bạn muốn. Douglas Crockford đã viết khá nhiều về nhiều cách khác nhau để làm kế thừa trong javascript.

Tôi sẽ đồng ý với casablanca ở trên rằng việc có thể kiểm tra loại bằng cách sử dụng "instanceof" là một lợi thế tốt đẹp khi trả về "this". Có lẽ tôi sẽ xem xét lại "protype" và "this" về một dự án tương lai. Bây giờ, mặc dù, tôi nhận được cùng tốt mà không có họ.

+1

Về 'this': cũng đọc Peter Michaux' [JavaScript Widgets Without this this "] (http://michaux.ca/articles/javascript-widgets-without-this) –

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