__Proto__ trong javascript
Hôm nay rảnh rỗi, đảo qua đảo lại trên Kipalog, cơ mà chưa thấy ai viết bài về vấn đề này (hay có ai viết rồi mà tìm hoài hổng ra). Thế nên là thôi thì rảnh rỗi viết tí cho đỡ buồn. Prototype - Dịch là nguyên mẫu, bản thân là một hình thái phân tách và lưu trữ dữ liệu. Có thể rất nhiều người đã từng biết đến Prototype Design Pattern, Prototype Function-base or function prototype (hay còn gọi là abstract method), tuy nhiên thì theo quan điểm cá nhân của em thì Prototype là một hệ tư tưởng (giống như OOP vs Functional Programming, SQL và NoSQL, ... ) thì Prototype sẽ đối trọng với hệ tư tưởng Object Class. Nghe vui tai không :)). Cơ mà bình thường Object Class là OOP rồi, vậy thì cái Prototype này là Functional Programming à ? À cũng không hẳn, nó là một cách khác để tổ chức object class song song và tương đối biệt lập với Object Class. Chúng ta sẽ đi qua Prototype Function-base nhé: Prototype là object cơ bản (hiểu nôm na là abstract object) mỗi khi có một object được tạo ra.
Tại đây, để truy cập prototype của object 0 1 trỏ tới prototype của object myBird và nếu khai báo như trên, prototype của myBird chính là 4.1.1 Tìm kiếm theo thứ tự inheritance.Chúng ta có một ví dụ như sau:
Ở ví dụ phía trên chúng ta thấy:
1.2 ConstructorTrong OOP thông thường, khi khởi tạo mỗi class, chúng ta có constructor để khởi tạo object đó. Tuy nhiên vì trong Prototype-based programming, chúng ta khởi tạo một object từ một vị trí bất kỳ, không cần khai báo thuộc kiểu class nào. Do vậy, trong các ngôn ngữ Prototype-based programming, người ta sinh ra một kiểu constructor như sau:
Foo là một hàm thông thường, nhưng chúng ta đã biết, function thực chất chỉ là một loại object đặc biệt, do vậy, Foo ở đây cũng là một class. 5 là câu lệnh gán cho object Foo, một biến nội tại bằng giá trị truyền vào. Khi khởi tạo một object mới dựa trên một object cũ đã có, chúng ta khởi tạo bằng từ khóa 6:
Ở đây b và c là 2 object mới. Theo như OOP, chúng ta mong muốn 7 và 8 có chung một số property hoặc method. Vậy chúng ta làm thế nào ? Sử dụng từ khóa 9
Khi chúng ta khai báo 0, thực tế, 7 đã link 0 tới 3.Vậy nên khi chúng ta gọi 4 -> thực tế đang gọi 5 hay nói cách khác là 6. Nếu thay đổi giá trị 7 này, toàn bộ các object link 0 tới 3 (hay nói cách khác là toàn bộ object kế thừa từ 0) sẽ thay đổi giá trị.=> Việc khai báo Foo.prototype thực tế không khác gì việc chúng ta đang khai báo property hay method trong OOP thông thường. Nói cách khác, đây chính là cách khai báo khởi tạo những giá trị trong object của Prototype-based programming. Nhưng nên lưu ý, đặc điểm của Prototype là nó chỉ link, chứ không tạo mới. Do vậy thực tế các giá trị này đều trỏ vào cùng một nơi. Đối với OOP thông thường, vì những property hay method được định nghĩa sẵn từ trước khi sử dụng nên hầu như không có trường hợp thay đổi lúc Run-time. Tuy nhiên với Prototype-based programming thì có thể. Giả dụ, chúng ta có thể làm như sau:
NOTE: Ở đây có một lưu ý, tại sao lại dùng 5 mà không dùng 2 ?Đó là vì, nếu sử dụng 2, hệ thống sẽ hiểu là chúng ta đang muốn set một biến 7 cho 7 tại scope 7, chứ không phải tại scope 7. Khi đã set 2 rồi, theo như 1.1, hệ thống sẽ luôn lấy giá trị x này. Kể cả khi chúng ta set giá trị 9 như sau:
Chỉ khi delete biến 7 tại scope 7 thì khi gọi 4 lần nữa, hệ thống sẽ tìm từ 0 của nó.1.3 How about static ?Trong OOP, đôi khi, chúng ta cần sử dụng những static property, static method, khai báo trong class. Vậy đối với Prototype-based programming thì liệu có thể làm vậy không ? Chúng ta khai báo trực tiếp trong object Foo phía trên:
Với ECMAScript 6 ra đời, chúng ta lại được quay lại các từ khóa 4, 5, 6, 7, ... tuy nhiên, tất cả những thứ đó, thực ra chỉ là thay thế cho những thứ chúng ta vừa tìm hiểu phía trên. Có nghĩa, bản chất của Prototype-based programming thì không thay đổi, chỉ có từ khóa giúp chúng ta dễ viết mã code hơn giống với OOP.NOTE : Những thứ mà prototype base làm được, còn OOP thì không ? Trong OOP đối với các ngôn ngữ biên dịch, việc ép kiểu (Đặc biệt là ép kiểu đối với các lớp kế thừa) là chuyện thường xuyên. Tuy nhiên JS không như vậy, vì nó không yêu cầu khai báo kiểu dữ liệu trước khi gọi. Ấy thế nhưng cũng có một số trường hợp, chúng ta cần ép kiểu cho một đối tượng. |