2011-08-03 33 views
6

Tôi vừa có Javascript: Các bộ phận tốt của Douglas Crockford và tôi đang gặp một số khó khăn trong việc hiểu một trong những ví dụ của ông về nguyên mẫu. Mã trong sách đọc như sau:nhầm lẫn về tập thể dục javascript

if (typeof Object.create !== "function") { 
    Object.create = function(o) { 
     var F = function() {} 
     F.prototype = o; 
     return new F; 
    }; 
} 

Tôi giả định rằng mã này được sử dụng để nhắm mục tiêu mẫu thử của hàm. Nhưng tại sao lại sử dụng một cách tiếp cận phức tạp như vậy? Tại sao không chỉ sử dụng variable .prototype? Crockford là chuyên gia hàng đầu về Javascript vì vậy tôi chắc chắn có một lý do chính đáng để sử dụng mô hình này. Bất cứ ai có thể giúp tôi hiểu nó tốt hơn? Bất kỳ trợ giúp sẽ được đánh giá cao.

Trả lời

5

Trong ECMAScript 3, các nhà điều hành new là cách tiêu chuẩn duy nhất để thiết lập [[Prototype]]sở hữu nội của một đối tượng, trong trường hợp này, Crockford là chỉ sử dụng một hàm xây dựng tạm thờiF cho mục đích đó.

Các o đối số của phương pháp đó, được đặt làm prototype tài sản của các nhà xây dựng tạm thời, và bằng cách gọi new F(); nó xây dựng một đối tượng trống mới được thừa kế từ F.prototype (xem this question để biết thêm chi tiết về cách new công trình).

Ví dụ:

var a = { a: 1 }; 
var b = Object.create(a); // b inherits from a 
b.a; // 1 

Trong ví dụ trên, chúng ta có thể nói rằng [[Prototype]] điểm bất động sản nội bộ của b-a.

Object.getPrototypeOf(b) === a; // true 

Nói cách khác, b được kế thừa từ a.

Với ví dụ tương tự, chúng ta có thể sử dụng một constructor rỗng, ví dụ:

function F(){} 
F.prototype = a; 

var b = new F(); // b again inherits from a (F.prototype) 

Cũng cần nhớ rằng prototype tài sản của các chức năng khác với [[Prototype]] tài sản đó tất cả các đối tượng có, prototype tài sản của chức năng này là được sử dụng khi chúng được gọi với toán tử mới, để xây dựng một đối tượng mới kế thừa từ thuộc tính đó. Ngoài ra, hãy lưu ý rằng hiện nay, Tiêu chuẩn ECMAScript 5 đang được triển khai và phần này không phù hợp 100% với thông số kỹ thuật, trên thực tế, có một số tính năng của phương pháp Object.create tiêu chuẩn that cannot be emulated on ES3.

Xem thêm:

+0

@ CMS - nhưng trong trường hợp này, 'Object.create' được đặt thành một hàm trống. Vì vậy, không có thừa kế ở đây ... phải không? Ngoài ra, vì 'Object.create' là một phương thức của hàm tạo' Object', việc thiết lập nó bằng một hàm rỗng sẽ là 'null' đúng không? – dopatraman

+0

@codeninja, tôi không hiểu tại sao bạn nói 'Object.create' là * đặt * thành một hàm * trống *, có thể là do dòng cuối cùng (' return new F; ') ??? Dòng cuối cùng đó trả về một đối tượng mới gọi hàm tạo 'F' (một đối tượng kế thừa từ' F.prototype'), nó có thể trông không quen thuộc vì các dấu ngoặc đơn bị thiếu ở cuối, nhưng chúng là tùy chọn khi bạn sử dụng 'new' 'toán tử (' new F(); 'tương đương với' new F; ') ... – CMS

+0

@ CMS - Mã đọc' Object.create = var F' được đặt '=' thành 'function() { } '. không có nghĩa là nó có ý nghĩa nào đó được đặt thành một hàm trống không? – dopatraman

0

Phương thức tạo này sẽ khởi tạo một đối tượng mới cho đối tượng được truyền làm mẫu thử nghiệm.

+0

@ Nathan_Romano - tại sao không chỉ sử dụng đối tượng 'mới'? – dopatraman

3
var bar = Object.create(foo) 

vs

var bar = new Object() 

là người đầu tiên barfoo như nguyên mẫu của nó; thứ hai có Object làm nguyên mẫu của nó.

+0

Typo: "cái thứ hai có' Object' làm nguyên mẫu của nó "phải là" cái thứ hai có 'Object.prototype' làm nguyên mẫu của nó ..." ('Object' chỉ là hàm dựng) – CMS

+0

@ Claudiu - trong trường hợp này 'Object.create' được đặt thành' function() ', nó không gán một nguyên mẫu cho bất kỳ biến nào. – dopatraman

1

Mã này là dành cho việc triển khai hoạt Javascript cũ không hỗ trợ Object.create, được xác định trong tiêu chuẩn ECMAScript 5 phát hành vào Tháng Mười Một 2009.

Nhiều người nói cách ưa thích để tạo một đối tượng là chỉ định một mẫu thử nghiệm cho nó tại thời điểm tạo ra. Điều này có thể được gọi là differential inheritance hoặc prototypal inheritance. Trên thực tế, đó là những gì Object.create thực hiện:

var protoCircle = {x: 0, y: 0, radius: 1, color:"black"}; 
var myCircle = Object.create(protoCircle); 
myCircle.x = 3; 
myCircle.color = "green"; 

Điều này làm cho vòng tròn bán kính màu xanh lá cây 1 ở giữa (3,0).

Lý do mã quá phức tạp trước khi Object.create được thêm vào JavaScript, cách duy nhất để đặt nguyên mẫu của đối tượng là là tạo ra nó với toán tử new. Các đối tượng được tạo ra với new nhận được, làm nguyên mẫu của chúng, giá trị của thuộc tính prototype của hàm tạo. Nó chắc chắn khó hiểu, nhưng thuộc tính prototype KHÔNG phải là nguyên mẫu của một đối tượng. Với đối tượng hàm f, f.prototype là đối tượng sẽ được gán làm nguyên mẫu của tất cả các đối tượng được xây dựng thông qua new f(). Nguyên mẫu thực của một đối tượng được gọi là [[prototype]] hoặc __proto__ nhưng bạn không thể truy cập chúng trong ECMAScript chuẩn. Bối rối, eh?

Như một lưu ý phụ. đặc điểm kỹ thuật ES5 có đặc điểm kỹ thuật được cải tiến hơn Object.prototype so với thông số Crockford được xác định. Phải mất một đối tượng thứ hai để cấu hình các thuộc tính của đối tượng đang được định nghĩa.