CHỈNH SỬA tháng 2 năm 2012: câu trả lời dưới đây không còn chính xác nữa. __proto__ đang được thêm vào ECMAScript 6 dưới dạng "tùy chọn quy chuẩn" có nghĩa là nó không bắt buộc phải được triển khai nhưng nếu có, nó phải tuân theo bộ quy tắc đã cho. Điều này hiện vẫn chưa được giải quyết nhưng ít nhất nó sẽ chính thức là một phần trong đặc tả của JavaScript.
Câu hỏi này phức tạp hơn rất nhiều so với bề ngoài, và vượt quá mức lương của hầu hết mọi người liên quan đến kiến thức về nội bộ Javascript.
Các prototype
tài sản của một đối tượng được sử dụng khi tạo các đối tượng con mới của đối tượng đó. Việc thay đổi nó không phản ánh trong bản thân đối tượng, đúng hơn được phản ánh khi đối tượng đó được sử dụng làm phương thức khởi tạo cho các đối tượng khác và không có tác dụng gì trong việc thay đổi nguyên mẫu của một đối tượng hiện có.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Các đối tượng có thuộc tính [[nguyên mẫu]] bên trong trỏ đến nguyên mẫu hiện tại. Cách hoạt động của nó là bất cứ khi nào một thuộc tính trên một đối tượng được gọi, nó sẽ bắt đầu từ đối tượng và sau đó đi lên qua chuỗi [[nguyên mẫu]] cho đến khi nó tìm thấy một kết quả phù hợp hoặc không thành công sau nguyên mẫu Đối tượng gốc. Đây là cách Javascript cho phép xây dựng thời gian chạy và sửa đổi các đối tượng; nó có một kế hoạch để tìm kiếm những gì nó cần.
Các __proto__
bất động sản tồn tại trong một số hiện thực (rất nhiều bây giờ): bất kỳ thực hiện Mozilla, tất cả những cái webkit tôi biết, một số người khác. Thuộc tính này trỏ đến thuộc tính [[nguyên mẫu]] bên trong và cho phép tạo sau sửa đổi trên các đối tượng. Bất kỳ thuộc tính và chức năng nào sẽ ngay lập tức chuyển đổi để khớp với nguyên mẫu do tra cứu theo chuỗi này.
Tính năng này, mặc dù hiện đã được tiêu chuẩn hóa, vẫn không phải là một phần bắt buộc của JavaScript và trong các ngôn ngữ hỗ trợ nó có khả năng cao khiến mã của bạn rơi vào danh mục "chưa được tối ưu hóa". Các công cụ JS phải cố gắng hết sức để phân loại mã, đặc biệt là mã "nóng" được truy cập rất thường xuyên và nếu bạn đang làm điều gì đó lạ mắt như sửa đổi __proto__
, chúng sẽ không tối ưu hóa mã của bạn.
Bài đăng này https://bugzilla.mozilla.org/show_bug.cgi?id=607863 thảo luận cụ thể về các triển khai hiện tại __proto__
và sự khác biệt giữa chúng. Mọi triển khai đều khác nhau, bởi vì đó là một vấn đề khó và chưa được giải quyết. Mọi thứ trong Javascript đều có thể thay đổi, ngoại trừ a.) Cú pháp b.) Các đối tượng máy chủ lưu trữ (DOM tồn tại bên ngoài Javascript về mặt kỹ thuật) và c.) __proto__
. Phần còn lại hoàn toàn nằm trong tay bạn và mọi nhà phát triển khác, vì vậy bạn có thể hiểu tại sao lại __proto__
nhô ra như ngón tay cái đau.
Có một điều __proto__
cho phép điều đó không thể làm được: việc chỉ định một nguyên mẫu đối tượng trong thời gian chạy tách biệt với phương thức khởi tạo của nó. Đây là một trường hợp sử dụng quan trọng và là một trong những lý do chính khiến __proto__
nó chưa chết. Nó đủ quan trọng để nó là một điểm thảo luận nghiêm túc trong việc xây dựng Harmony, hay sắp được gọi là ECMAScript 6. Khả năng chỉ định nguyên mẫu của một đối tượng trong quá trình tạo sẽ là một phần của phiên bản tiếp theo của Javascript và điều này sẽ chuông chỉ __proto__
ngày của được đánh số chính thức.
Trong ngắn hạn, bạn có thể sử dụng __proto__
nếu bạn đang nhắm mục tiêu các trình duyệt hỗ trợ nó (không phải IE và không IE bao giờ). Có khả năng nó sẽ hoạt động trong webkit và moz trong 10 năm tới vì ES6 sẽ không được hoàn thiện cho đến năm 2013.
Brendan Eich - re: Cách tiếp cận các phương thức Đối tượng mới trong ES5 :
Xin lỗi, ... nhưng có thể thiết lập __proto__
, ngoài trường hợp sử dụng trình khởi tạo đối tượng (tức là trên một đối tượng mới chưa thể truy cập, tương tự như Object.create của ES5), là một ý tưởng tồi. Tôi viết điều này có thể thiết kế và thực hiện được __proto__
hơn 12 năm trước.
... việc thiếu phân tầng là một vấn đề (xem xét dữ liệu JSON với một khóa "__proto__"
). Và tệ hơn, khả năng thay đổi có nghĩa là việc triển khai phải kiểm tra các chuỗi mẫu thử nghiệm theo chu kỳ để tránh bỏ lọt. [yêu cầu kiểm tra liên tục cho đệ quy vô hạn]
Cuối cùng, việc đột biến __proto__
trên một đối tượng hiện có có thể phá vỡ các phương thức không chung chung trong đối tượng nguyên mẫu mới, không thể hoạt động trên đối tượng nhận (trực tiếp) __proto__
đang được thiết lập. Nói chung, đây chỉ đơn giản là thực hành xấu, một dạng nhầm lẫn có chủ ý.