OOP Trong Javascript Có Gì Khác Với Ngôn Ngữ Khác?
NỘI DUNG BÀI VIẾT
Trước khi đọc bài viết này, bạn nên ôn lại kiến thức về object và prototype trong Javacript. Trước khi phân tích về OOP trong JavaScript, mình sẽ nhắc lại sơ 1 số tính chất trong OOP.
Các tính chất của OOP
Trong lập trình hướng đối tượng (OOP) có 4 tính chất là tính đóng gói (Encapsulation), tính kế thừa (Inheritance), tính đa hình (Polymorphism) và tính trừu tượng (Abstraction)
1. Encapsulation (Tính đóng gói):
Tính đóng là kỹ thuật giúp bạn che giấu được những thông tin bên trong đối tượng. Mục đích chính của tính đóng gói là giúp hạn chế các lỗi khi phát triển chương trình. Tính chất này không cho phép người sử dụng các đối tượng thay đổi trạng thái nội tại của một đối tượng. Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó. Việc cho phép môi trường bên ngoài tác động lên các dữ liệu nội tại của một đối tượng theo cách nào là hoàn toàn tùy thuộc vào người viết mã. Đây là tính chất đảm bảo sự toàn vẹn của đối tượng.
Các lợi ích chính mà tính đóng gói mang lại:
- Hạn chế được các truy xuất không hợp lệ tới các thuộc tính của đối tượng.
- Giúp cho trạng thái của đối tượng luôn đúng.
- Giúp ẩn đi những thông tin không cần thiết về đối tượng.
- Cho phép bạn thay đổi cấu trúc bên trong lớp mà không ảnh hưởng tới lớp khác.
2. Inheritance(Tính kế thừa):
Kế thừa trong lập trình hướng đối tượng chính là thừa hưởng lại những thuộc tính và phương thức của một lớp. Có nghĩa là nếu lớp A kế thừa lớp B thì lớp A sẽ có những thuộc tính và phương thức của lớp B. Lớp được thừa hưởng những thuộc tính và phương thức từ lớp khác được gọi là dẫn xuất (Derived Class) hay lớp Con (Subclass) và lớp bị lớp khác kế thừa được gọi là lớp cơ sở (Base Class) hoặc lớp cha (Parent Class).
Các lợi ích của tính kế thừa:
- Giúp tái sử dụng lại code.
- Tăng khả năng mở rộng của chương trình.
3. Polymorphism(Tính đa hình):
Tính đa hình thể hiện thông qua việc gửi các thông điệp (message). Việc gửi các thông điệp này có thể so sánh như việc gọi các hàm bên trong của một đối tượng. Các phương thức dùng trả lời cho một thông điệp sẽ tùy theo đối tượng mà thông điệp đó được gửi tới sẽ có phản ứng khác nhau. Người lập trình có thể định nghĩa một đặc tính (chẳng hạn thông qua tên của các phương thức) cho một loạt các đối tượng gần nhau nhưng khi thi hành thì dùng cùng một tên gọi mà sự thi hành của mỗi đối tượng sẽ tự động xảy ra tương ứng theo đặc tính của từng đối tượng mà không bị nhầm lẫn.
4. Abstraction(Tính trừu tượng):
Tính trừu tượng là một tính chất mà chỉ tập trung vào những tính năng của đối tượng và ẩn đi những thông tin không cần thiết. Tính chất này giúp bạn trọng tâm hơn vào những tính năng thay vì phải quan tâm tới cách mà nó được thực hiện.
Trong phạm vi bài viết này, chúng ta sẽ bàn về 3 đặc tính của OOP (tính đóng gói, tính kế thừa, tính đa hình), so sánh cách hiện thực chúng trong Java và JavaScript.
OOP trong Javascript
Javascript thì khác, không như Java, chúng ta cần phải áp dụng một vài thủ thuật để thực hiện các đặc tính này.
1. Tính đóng gói
Trong Javascript, để thực hiện tính bao đóng, ta có thể tạo ra 1 Constructor Function, đóng gói toàn bộ các trường và hàm vào 1 object. Thông thường, các bạn hay khai báo như sau:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.showName = function() {
console.log(this.firstName + ' ' + this.lastName);
};
}
var psn1 = new Person('Khoa', 'Nguyen');
// các property khai báo vào biến this có thể bị truy xuất từ bên ngoài
// object không còn bao đóng nữa
psn1.firstName = 'changed';
console.log(ps1.firstName); // changed
Với các khai báo này, tính bao đóng không được đảm bảo. Các property có thể bị truy cập, thay đổi từ bên ngoài. Ở đây, ta phải sử dụng biến cục bộ.
function Person(firstName, lastName) {
var fstName = firstName;
var lstName = lastName;
this.setFirstName = function(firstName) {
fstName = firstName;
};
this.getFirstName = function() {
return fstName;
};
this.setLastName = function(lastName) {
lstName = lastName;
};
this.getLastName = function() {
return lstName;
};
}
var person1 = new Person('Khoa', 'Nguyen');
console.log(person1.fstName); // Undefined, không thể truy cập được
console.log(person1.getFirstName()); // Khoa
Các biến cục bộ này chỉ có thể truy xuất trong Constructor Function, nó tương đương với các trường private
trong Java.
Trong javascript, không có cách nào để tạo ra các trường protected
(Chỉ có thể truy cập từ class kế thừa) như Java và C# được.
2. Tính kế thừa
Trong Javascript không có từ khóa extends cũng như class, vậy nên Prototype (and Prototype chains) là sự triển khai tính kế thừa đối tượng của Javascript.
Ví dụ:
function Person() {
this.firstName = 'Per';
this.lastName = 'son';
this.sayName = function() { return this.firstName + ' ' + this.lastName };
}
// Viết một Constructor Function khác
function SuperMan(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Ta muốn SuperMan sẽ kế thừa các thuộc tính của Person
// Sử dụng prototype để kế thừa
SuperMan.prototype = new Person();
// Tạo một object mới bằng Constructor Function
var sm = new SuperMan('Khoa', 'Nguyen');
sm.sayName(); // Khoa Nguyen. Hàm này kế thừa từ prototype của Person
Khi trình thông dịch JS kiểm tra thuộc tính đối tượng định nghĩa cho nó, trước tiên nó kiểm kiểm tra object trước. Nếu object không có thuộc tính được định nghĩa, nó sẽ kiểm tra prototype của đối tượng với cùng thuộc tính, nếu nó được tìm thấy, nó sẽ trả về thuộc tính đó. Nó khác với OOP trong Java là prototype object có thể truy cập vào đối tượng tạo ra trước vào sau bất kể khi nào có sự thay đổi nào trên prototype
function Bread() {}; // constructor function
let brownBread = new Bread(); // object of type "Bread"
let sodaBread = new Bread(); // object of type "Bread"
Bread.prototype.toast = function() {
console.log('I am toasting!');
}; // set the function on a toast property on the prototype
// inherited prototype is accessible!
brownBread.toast(); // I am toasting!
sodaBread.toast(); // I am toasting!
3. Tính đa hình và trừu tượng
Đối với tính đa hình và tính trừu tượng, việc áp dụng 2 tính chất này trong Javascript là không rõ ràng. Do đó mình sẽ không trình bày trong bài viết này
Việc áp dụng lập trình hướng đối tượng vào JavaScript là tương đối khó. Tuy nhiên, nếu bạn nắm vững những kiến thức cơ bản mà mình đã trình bày trên đây, thì mình tin chắc rằng bạn sẽ dễ dàng tìm hiểu thêm và áp dụng lập trình hướng đối tượng trong JavaScript.
Tạm kết
Như vậy trong bài viết này, chúng ta đã cùng tìm hiểu về OOP trong javascript. Bạn thấy thế nào về JS, hãy đưa ra những ý kiến trong quá trình sử dụng js nhé. Nếu các bạn thấy bài viết hữu ích hãy share cho mọi người tham khảo!
Nguồn: codelearn.io
Tham gia KHOÁ HỌC CGC JAVA TRỞ THÀNH LẬP TRÌNH VIÊN JAVA FULL-STACK TRONG 6 THÁNG
Leave a Reply