2015-11-23 55 views
6

Theo this, chức năng kế thừa từ FunctionFunction từ Function.prototype lần lượt:Sự khác nhau giữa hàm và Function.prototype

Đối tượng Function toàn cầu không có phương pháp hoặc tài sản của riêng mình, tuy nhiên, vì nó là một chức năng chính nó nó kế thừa một số phương pháp và tài sản thông qua chuỗi nguyên mẫu từ Function.prototype.

Điểm của Function.prototype là gì? Tại sao không di chuyển thuộc tính của nó sang Function và để Function.prototypeundefined? Thay vào đó, các hàm sẽ có nguồn gốc từ Function.

Cùng đi cho Object, vv

+3

Tôi sẽ hình dung rằng đó là vì các thuộc tính mẫu thử được chia sẻ giữa tất cả các cá thể, không giống như các thuộc tính thể hiện cục bộ cho mỗi cá thể. –

+0

> "Chức năng sẽ được bắt nguồn từ Chức năng thay thế". Tin rằng đây là nguồn gây nhầm lẫn của bạn. Không chắc bạn đã đọc chính xác ở đâu, nhưng các hàm không thể được bắt nguồn từ các hàm trong một ý nghĩa nguyên mẫu. –

+0

@ nikc.org Được rồi, nhưng tại sao từ 'Function.prototype'? Hoặc không phải là các thuộc tính thực sự được kế thừa nếu chúng ta thực hiện 'f.prototype = Function', trong đó' f' là một hàm? Ý tôi là, nếu bạn muốn kế thừa từ một hàm bạn làm 'f.prototype = super_f' và không phải' f.prototype = super_f.prototype', phải không? – Downvoter

Trả lời

6

chức năng kế thừa từ Function

Bạn đang trích dẫn MDN lỏng lẻo. Những gì nó thực sự nói là: đối tượng

chức năng kế thừa từ Function.prototype

Lưu ý rằng trên trang MDN, từ ban đầu "chức năng" trong câu trên được viết hoa, nhưng chỉ vì nó là tại bắt đầu câu, không phải vì nó đang đề cập đến đối tượng JS Function. Nó đề cập đến các hàm cũ thông thường được khai báo là function() { }.

Hãy nhớ rằng MDN chỉ được viết bởi những người chết. Tôi thích họ không sử dụng từ "kế thừa" và "thừa kế", chưa kể "có nguồn gốc". JS không có khái niệm thừa kế theo nghĩa nghiêm ngặt của từ đó. Nếu bạn sử dụng thuật ngữ này, bạn sẽ kết thúc tự gây nhầm lẫn. JS là gì có nguyên mẫu liên kết với các đối tượng. Khi truy cập một thuộc tính trên một đối tượng, nếu nó không được tìm thấy, nguyên mẫu sẽ được tham khảo. Nếu không tìm thấy ở đó, kể từ khi một nguyên mẫu cũng là một đối tượng với một nguyên mẫu, nguyên mẫu của nguyên mẫu được tư vấn, và như vậy lên chuỗi.

Vì vậy, câu trên sẽ tốt hơn được viết là "đối tượng chức năng có dạng nguyên mẫuFunction.prototype".

Đối tượng JS Function không liên quan trực tiếp với Function.prototype, khác hơn so với thực tế là Function.prototype là một tài sản của Function, và, vì đối tượng Function là chính nó một chức năng, nó chính nó có Function.prototype như nguyên mẫu của nó. Bất kỳ thuộc tính nào có thể hoặc không thể hiện diện trên Function hoặc treo trên đó bởi bạn, không có gì liên quan đến chuỗi nguyên mẫu và không được "thừa kế" bởi bất kỳ ai.

Khi bạn làm (function() { }).call(), thuộc tính/phương pháp call lần đầu tiên được tìm kiếm trên chính đối tượng hàm; nếu nó không tồn tại ở đó, như bình thường thì không, sau đó nó được nhìn lên trên nguyên mẫu được gán nội tại khi hàm được khai báo, là Function.prototype. Bạn sẽ đặt phương thức nào khác như call hoặc apply nếu không có trên Function.prototype? Những gì khác bạn sẽ gọi nguyên mẫu tự động được giao cho các chức năng khác hơn là Function.prototype?

Để sang một bên, lưu ý rằng Function.call sẽ giải quyết chính xác đến hàm call bên trong. Tại sao? Không phải vì đó là nơi mà cuộc sống call, hoặc vì đó là nơi mà các chức năng thông thường "kế thừa" call, nhưng vì, như tôi đã đề cập trước đó, Function chính nó là một hàm, và do đó có nguyên mẫu Function.prototype, call có thể được tìm thấy trên chuỗi nguyên mẫu.

Điểm của Function.prototype là gì? Tại sao không di chuyển thuộc tính của nó sang Function và để Function.prototype không được xác định? Thay vào đó, các hàm sẽ có nguồn gốc từ Function.

X.prototype là thuộc tính trên X được sử dụng làm nguyên mẫu cho các đối tượng được tạo bằng cách sử dụng X làm hàm tạo. Do đó, để gán nguyên mẫu chính xác cho các đối tượng được tạo bằng cách sử dụng Function làm hàm tạo (bao gồm các hàm được khai báo là function x() { }), nguyên mẫu phải có mặt là thuộc tính prototype trên Function.

+0

Crap, hoàn toàn quên 'Function.prototype' chỉ là một thuộc tính, không phải là một đối tượng riêng biệt. Dù sao, tại sao không di chuyển các thuộc tính của đối tượng được tham chiếu bởi 'Function.prototype' vào' Function'? Nếu bạn có hai hàm, 'f' và' g', thì bạn sẽ nói 'f.prototype = g' và không phải' f.prototype = g.prototype', đúng không? Và liên quan đến "bản thân nó có Function.prototype làm nguyên mẫu của nó" - điều đó sẽ không dẫn đến một vòng lặp đệ quy vô hạn? Và xây dựng dựa trên điều đó, khi nào trình biên dịch ngừng leo lên chuỗi nguyên mẫu? – Downvoter

+0

Không, vì nguyên mẫu của 'Function.prototype' là' Object.prototype'. Động cơ ngừng leo dây chuyền nguyên mẫu khi nó gặp một vật thể không có nguyên mẫu. 'Object.getPrototypeOf (Object.prototype) == null'. –

+0

Vì vậy, 'Function.prototype.prototype === Object.prototype'? Và không "bản thân nó có Function.prototype làm nguyên mẫu của nó." có nghĩa là 'Function.prototype === Function.prototype'? Vâng, điều đó rõ ràng là đúng nhưng tôi không hiểu nó. :( – Downvoter

2

Chức năng trên nguyên mẫu chỉ được tạo ra một lần và chia sẻ giữa mỗi trường hợp. Các hàm được tạo trong hàm tạo được tạo ra như các đối tượng mới cho mỗi đối tượng mới được tạo bằng hàm tạo.

Như một chức năng quy tắc chung nên được trên nguyên mẫu vì chúng thường sẽ không được sửa đổi cho các đối tượng khác nhau cùng loại, và điều này có một lợi ích bộ nhớ/hiệu suất nhỏ. Các thuộc tính khác như đối tượng và mảng nên được định nghĩa trong hàm tạo, trừ khi bạn muốn tạo thuộc tính tĩnh, được chia sẻ, trong trường hợp này bạn nên sử dụng mẫu thử nghiệm.

của nó dễ dàng hơn để xem sự phân biệt với các đối tượng bình thường hoặc mảng chứ không phải là chức năng

function Foo(){ 
    this.bar = []; 
} 
var fooObj1 = new Foo(); 
var fooObj2 = new Foo(); 

fooObj1.bar.push("x"); 
alert(fooObj2.bar) //[] 
as opposed to: 

function Foo(){ 
} 

Foo.prototype.bar = [] 
var fooObj1 = new Foo(); 
var fooObj2 = new Foo(); 

fooObj1.bar.push("x"); 
alert(fooObj2.bar) //["x"] 
+1

Điều này là tất cả sự thật, nhưng không thực sự là những gì OP đã nói về, đó là cấu trúc thừa kế cho các chức năng bản thân. –

0

Bạn cần Function.prototype vì nếu bạn muốn mở rộng chức năng, xem xét việc này:

Function.prototype.moo = 5; 
function x() { }; 
console.log(x.moo); // 5 

mỗi chức năng bạn thực hiện hiện nay có tài sản moo, so với:

Function.quack = 6; 
function b() {}; 
console.log(b.quack); // undefined 

Đây không phải là đúng nếu bạn chỉ cần tát một tài sản vào Function. Mỗi hàm KHÔNG thừa hưởng các thuộc tính được gán cho Function, đó là lý do tại sao bạn cần Function.prototype.

+0

"Điều này là không đúng nếu bạn chỉ tát một tài sản vào' Chức năng' "- tại sao không? Tôi sẽ tiếp tục đọc cuốn sách nhỏ gọn của tôi bây giờ, có lẽ quesion của tôi chỉ đơn giản là dựa trên "không có kiến ​​thức" của tôi. – Downvoter

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