Tôi biết có những câu hỏi tương tự như thế này, nhưng tôi muốn xem liệu những câu trả lời đó vẫn là các tối ưu hóa hợp lệ trong các công cụ Javascript mới.Chức năng bên trong hàm dựng vs nguyên mẫu
Theo tôi, lợi ích lớn nhất về việc xác định chức năng bên trong constructor là bạn có thể dễ dàng tránh được việc phải biết giá trị của từ khoá 'này':
var Person = function() {
var self = this;
self.firstName = null;
self.lastName = null;
self.fullName = function() {
return self.firstName + self.lastName;
};
};
Cách tiếp cận này được khuyến khích bởi Knockout Managing 'this'. Đây là một lợi thế lớn, đặc biệt là khi mã được sửa đổi bởi nhiều nhà phát triển vì nó thực sự đơn giản để hiểu và sử dụng.
Cách tiếp cận khác sẽ được sử dụng nguyên mẫu đối tượng:
var Person = function() {
this.firstName = null;
this.lastName = null;
};
Person.prototype.fullName = function() {
return this.firstName + this.lastName;
};
Trong trường hợp này có ưu điểm hiệu suất vì chức năng đối tượng sẽ được tạo ra một lần. Tuy nhiên vấn đề chính tôi có với nó là nó có thể phức tạp để xử lý các từ khóa 'này'. Ví dụ trên là rất đơn giản, nhưng nếu bạn có trình xử lý sự kiện, forEach calls, jQuery each() các cuộc gọi, các phương thức được gọi từ các ngữ cảnh khác nhau, v.v., thật dễ dàng để sử dụng điều này.
Tất nhiên, nếu bạn hiểu cách 'này' hoạt động và nhận thức được cách thức các phương thức được gọi, bạn không nên có nhiều vấn đề. Tuy nhiên, theo kinh nghiệm của tôi, điều này cần có thời gian và rất dễ xảy ra lỗi, đặc biệt khi mã được tạo bởi nhiều nhà phát triển.
Tôi biết rằng các công cụ JS mới, như V8, đang áp dụng tối ưu hóa cho các trường hợp bạn khai báo hàm bên trong hàm tạo bằng cách tạo các lớp ẩn: How the V8 engine works?. Vì vậy, câu hỏi của tôi là, với những tối ưu hóa được thực hiện bởi các công cụ JS mới và sự phức tạp của việc phải xử lý từ khóa 'này', liệu nó vẫn có ý nghĩa để sử dụng phương pháp tiếp cận dựa trên nguyên mẫu không? Không. Những gì tôi sẽ mất bằng cách sử dụng cách tiếp cận của việc đưa tất cả mọi thứ bên trong constructor?
CẬP NHẬT 1:
Tôi vừa thực hiện một điểm chuẩn vi mô trên Chrome (phiên bản 42). Tôi tạo các đối tượng 1M với các hàm bên trong hàm tạo và các hàm trong nguyên mẫu. Nó là một đối tượng rất đơn giản với hai biến và ba hàm và kết quả giống như thế này:
Functions inside constructor: 1.91 seconds
Functions in prototype: 1.10 seconds
Âm thanh như ngay cả với những tối ưu hóa đó trong V8 vẫn nhanh hơn 73%. Tuy nhiên đây là một điểm chuẩn nhỏ. Không chắc chắn nếu đó sẽ là một sự khác biệt lớn trong các ứng dụng thế giới thực.
CẬP NHẬT 2:
Tôi cũng xem xét mức tiêu thụ bộ nhớ và cũng có những khác biệt lớn. Đối với các chức năng bên trong cấu trúc:
Shallow size: 64,000,120
Retained size: 336,001,128
cho các chức năng nguyên mẫu:
Shallow size: 40,000,000
Retained size: 40,000,000
Hoặc tối ưu hóa với lớp ẩn không phải là tốt hay tôi đang thiếu một cái gì đó về điều đó. Tôi đang sử dụng mã monomorphic (constructors không có args) theo đề nghị của V8, nhưng không chắc chắn nếu tôi đang làm một cái gì đó sai.
UPDATE 3:
Dưới đây là liên kết của bài kiểm tra tôi đã làm trong trường hợp ai đó có thể chỉ ra một cái gì đó sai trong đó: http://jsperf.com/dg-constructor-vs-prototype
FWIW, tôi đã thêm một trường hợp thử nghiệm thứ 3, các "POJO" mà không sử dụng nguyên mẫu hoặc từ khóa "mới", nó chỉ tạo ra một đối tượng với phương pháp nào và biến tư nhân. Nó có thể so sánh về hiệu năng với ví dụ về hàm tạo. Dù bằng cách nào, các phương pháp nguyên mẫu luôn luôn nhanh hơn, mặc dù với sự phức tạp thêm. http://jsperf.com/dg-constructor-vs-prototype/2 –
Cảm ơn Scott. Vâng, có vẻ như vào thời điểm này, cách hiệu quả nhất là sử dụng nguyên mẫu. Đó là một sự xấu hổ bởi vì tôi yêu sự đơn giản của việc gán 'điều này' cho 'bản thân' và chắc chắn rằng 'tự' chỉ vào đối tượng thay vì phải suy nghĩ 'cái này' trỏ tới điều gì. – dgaviola
Vâng, tôi hoàn toàn đồng ý. Đối với các đối tượng đơn giản (không thừa kế), sử dụng 'prototype' là không có gì khác hơn là tối ưu hóa vi mô, với nhược điểm là phải hiểu và quản lý cẩn thận việc sử dụng' this'. –