2015-04-26 25 views
5

sự khác biệt giữa 2 triển khai thừa kế nguyên chủng là gì, và xem xét rằng chúng tôi đang làm việc với 2 "nguyên mẫu" khác nhau (thuộc tính prototype mà chỉ về chức năng, và nguyên mẫu nội bộ), và làm thế nào để những hiện thực khác nhau về nguyên mẫu của họ tra cứu chuỗi? Ngoài ra, thực hiện đầu tiên (sử dụng thuộc tính mẫu thử nghiệm) có phụ thuộc vào việc sử dụng toán tử new của chúng tôi không?Sự khác nhau giữa 2 triển khai thừa kế prototypal này là gì?

Gán tài sản prototype một chức năng và sử dụng new điều hành:

function foo() {} 

foo.prototype.output = function(){ 
    console.log('inherits from Function.prototype property'); 
}; 

bar = new foo(); 
bar.output(); 

Lưu trữ một hàm trong một đối tượng theo nghĩa đen và sử dụng Object.create() phương pháp:

var foo = { 
    output: function(){ 
    console.log('inherits from the internal prototype'); 
    } 
}; 

var bar = Object.create(foo); 
bar.output(); 
+0

Một khác biệt là 'Object.create' là mới hơn, và không được hỗ trợ trong IE8 và dưới – keune

+0

Tôi không thấy nguyên chủng ** thừa kế ** trong ví dụ của bạn. – hindmost

+0

@hindmost bạn có thể xây dựng được không? – shmuli

Trả lời

3

Sự khác biệt chính là theo cách nó được sử dụng, và những mối nguy hiểm liên quan.

Một lực lượng đầu tiên bạn sử dụng new khi bạn muốn tạo một đối tượng mới. Cú pháp là khá xấu xí (SomeConstructor.prototype.method), và nó mang một lỗ hổng lớn: gọi một constructor mà thêm tài sản (this.name = nameParam ...) mà không new sẽ áp dụng việc xây dựng cho các đối tượng toàn cầu. Các hành vi của constructor là lạ (tạo đối tượng mới mà đại biểu để SomeConstructor.prototype, sau đó áp dụng constructor cho đối tượng mới, sau đó nếu constructor trả về một cái gì đó thay thế các đối tượng của một cái gì đó). Ngoài ra, trong ví dụ của bạn, chính bạn không thể sử dụng foo, bạn phải tạo một đối tượng mới để truy cập các chức năng của nó.

Điều thứ hai, Object.create, không buộc bạn phải sử dụng bất kỳ những đứa syntoxic. Bạn không có nguy cơ ô nhiễm toàn cầu. Đối tượng foo có các chức năng có thể đã được sử dụng mà không cần tạo một đối tượng mới và bar sẽ chỉ đơn giản là mượn các chức năng này. Kiểu mẫu này cũng có thể giúp các nhà máy (không cần new s để thay thế ở mọi nơi) và các hồ đối tượng nếu cần.

Eric Eliott talks about it very wellKyle Simpson wrote a whole book về ủy quyền mẫu thử!

Bây giờ, đây là cách tra cứu sẽ xảy ra:

  • Với các nhà xây dựng, tra cứu được thực hiện trên Constructor.prototype (không phải là thực tế nguyên mẫu nội bộ của các nhà xây dựng, nhưng tài sản prototype của nó Nếu bạn cảm thấy khó hiểu. , xin chúc mừng, bạn là con người). Các thuộc tính bổ sung được thiết lập trong hàm constructor. foo bản thân nó không được sử dụng cho việc tra cứu, foo.prototype (một lần nữa, không giống như foo.__proto__ mà điểm đến chức năng) là một trong những sử dụng cho nó.
  • Với Object.create tra cứu được thực hiện trên đối tượng chính nó (foo). Không có tài sản không phải là nguyên mẫu prototype trên đối tượng.

very funny diagrams on this page of Kyle Simpson's book giải thích thêm về điều này.

Thông tin thêm về new trong câu hỏi này: Is JavaScript's "new" keyword considered harmful?

+1

Chế độ nghiêm ngặt giải quyết vấn đề ô nhiễm toàn cầu. – jdphenix

+0

@Kyll những gì khác xa như "tra cứu" là có liên quan? Những triển khai này sử dụng 2 đối tượng 'nguyên mẫu' khác nhau, không? – shmuli

+0

Hãy để tôi chỉnh sửa! –

-1

Ví dụ đầu tiên - foo, là một hàm.

Ví dụ thứ hai - foo là một đối tượng.

trong ví dụ thứ hai, thanh trở thành phiên bản mới không có hàm tạo. Xem - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create, để thêm hàm tạo.

Như một lưu ý phụ, thực tiễn tốt nhất phổ biến mà các nhà xây dựng nên bắt đầu bằng một chữ cái viết hoa.

1

OK, trước hết, trong trường hợp bạn không biết, Object.create dựa trên mô hình sau bởi Douglas Crockford đề xuất (đọc thêm here):

function create (proto) { 
    function f() {} 
    f.prototype = proto; 
    return new f(); 
} 

Bây giờ, bạn phải lưu ý rằng mã trên không mang lại kết quả tương tự trong trường hợp bạn vượt qua null làm thông số.
Thuật toán ECMAScript để tạo đối tượng mới (đọc thêm here) nói rằng nếu nguyên mẫu của hàm được đặt thành null (hoặc bất kỳ đối tượng nào), khi bạn đang cố sử dụng cú pháp new f(), đối tượng mới được tạo sẽ kế thừa từ Object.prototype.
Nếu bạn sử dụng Object.create(null), đối tượng mới được tạo ra sẽ có [[Prototype]] bộ thành viên nội bộ của mình để null, có nghĩa là chuỗi nguyên mẫu sẽ dừng lại ở đó (đối tượng của bạn không nhận được hasOwnProperty và các công cụ khác từ Object.prototype như đối tượng bình thường sẽ).

var o1 = create(null); 
var o2 = Object.create(null); 
Object.getPrototypeOf(o1) === Object.prototype // true 
Object.getPrototypeOf(o2) === Object.prototype // false 
Object.getPrototypeOf(o2) === null // true 
Các vấn đề liên quan