11/08/2018, 20:35

Bàn về khái niệm Object trong Javascript

Nguồn: Bàn về khái niệm Object trong Javascript Nhắc lại về các kiểu dữ liệu trong Javascript, ta có 5 kiểu dữ liệu cơ bản và 1 kiểu dữ liệu phức hợp. 5 kiểu dữ liệu cơ bản bao gồm: Number, String, Boolean, Undefined và Null. Kiểu dữ liệu phức hợp là kiểu dữ liệu Object. Kiểu dữ liệu ...

Nguồn: Bàn về khái niệm Object trong Javascript

Nhắc lại về các kiểu dữ liệu trong Javascript, ta có 5 kiểu dữ liệu cơ bản và 1 kiểu dữ liệu phức hợp. 5 kiểu dữ liệu cơ bản bao gồm: Number, String, Boolean, Undefined và Null. Kiểu dữ liệu phức hợp là kiểu dữ liệu Object.
Kiểu dữ liệu Object được sử dụng rất thường xuyên trong Js vì nó rất biến hoá và mạnh mẽ, đây là khái niệm cơ sở cho hàng loạt các đặc điểm nổi bật khác của Javascript, ta hãy thử xem nó là gì nào.

1. Khái niệm Object là gì?

Về mặt định nghĩa, một đối tượng (một object) là một danh sách các item, mỗi item là một cặp name-value, trong đó value có thể là: các kiểu dữ liệu cơ bản, function, hay cũng có thể là một object khác (kiểu dữ liệu phức hợp).

Ta gọi mỗi item là một property(thuộc tính) của object nếu value của item đó có kiểu dữ liệu là kiểu phức hợp hoặc các kiểu dữ liệu cơ bản, ngược lại nếu value của item nó là một hàm (một function) thì ta gọi nó là method của object (phương thức của object).

Ta xét một ví dụ sau:

var myFirstObject = {
    firstName: "Richard",
    favoriteAuthor: "Conrad"
};

Ta thấy rằng, đối tượng object này là một danh sách các items, mỗi item (có thể là property hoặc method) được lưu trữ trong object bởi cặp giá trị name-value, trong trường hợp này thì các tên của property là ‘firstName’ và ‘favoriteAuthor’, tương ứng với các tên này là các giá trị “Richard” và “Conrad”.

Những cách để truy cập tới các thuộc tính của object

Để lấy được các giá trị của thuộc tính trong object, ta có thể truy cập tới tên của thuộc tính bằng toán tử ngoặc vuông [ ] hoặc dấu chấm ., minh hoạ như sau:

myFirstObject.firstName;                //Richard
myFirstObject['favoriteAuthor'];        //Conrad

Truy cập tới các thuộc tính không tồn tại của object sẽ cho ta giá trị là undefined.

Có một trường hợp nên chú ý, nếu tên của thuộc tính là số (tức là number), thì ta chỉ có thể truy cập bằng cách dùng dấu ngoặc vuông [ ] mà không thể dùng dấu chấm ., xem minh hoạ sau để hiểu rõ:

var myObject = {10: 'test1'}
myObject.10;                         //Throw Error
myObject['10'];                      //test1

2. Các cách để tạo ra Object

Thông thường, ta có 2 cách để tạo ra một object: dùng object literals và dùng Object constructor

Dùng Object literals

Mình không rõ tiếng Việt gọi literal là gì, nhưng đại khái là sẽ dùng cặp ngoặc nhọn { } để tạo một object. Literal có thể hiểu theo ngữ cảnh nào đó là việc “sử dụng chuỗi thuần tuý”. Đoạn code sau minh hoạ cho điều này:

var myBook = {10: 'test1'};  //đối tượng có 1 thuộc tính

//đối tượng có 1 thuộc tính và 1 phương thức (method)
var myCar = {
   brand: 'Toyota',
   run: function(){
      console.log('running');
   }
};

Dùng Object constructor

Cách này sẽ sử dụng phương thức khởi tạo (constructor) của kiểu dữ liệu Object để tạo ra các object. Phương thức khởi tạo này là một hàm để tạo ra các object mới, ta dùng kèm từ khoá new:

//Tạo 1 đối tượng mới
var myApple = new Object();

//Thêm các thuộc tính cho đối tượng
myApple.color = 'red';
myApple.shape = 'round';
myApple.howSweet = function(){
   console.log('I am sweet');
};

Trong Js, thì các thuộc tính của object có thể là các kiểu dữ liệu cơ bản, các phương thức, hay cũng có thể là các object con. Kiểu dữ liệu Object cho ta một cách sử dụng rất linh hoạt và mạnh mẽ.

Tạo hàng loạt các Object cùng loại như thế nào?

Ở trên, ta đã biết cách để tạo ra từng object riêng biệt, thế còn việc tạo hàng loạt các object giống nhau (có cùng tên thuộc tính và số lượng thuộc tính) như thế nào? Ta cũng có 2 cách để làm việc này: sử dụng mẫu khởi tạo, và sử dụng prototype.

Sử dụng mẫu khởi tạo

Cách này sử dụng từ khoá function để tạo ra một hàm khởi tạo đối tượng, dùng từ khoá this để gán các thuộc tính cho đối tượng:

function Fruit (_color, _name){
   this.color = _color;
   this.name = _name;

   this.showName = function(){
      console.log(this.name);
   }
};

Với hàm khởi tạo này, ta có thể tạo hàng loạt các đối tượng kiểu Fruit như sau:

var mangoFruit = new Fruit('yellow', 'Mango');
var appleFruit = new Fruit('red', 'Apple');

Con trỏ this là một thứ rất thần thánh và kì quặc trong Javascript, bạn nên cẩn thận khi sử dụng nó. Bạn có thể ôn lại về this ở Link này: Con trỏ this trong Javascript

Sử dụng prototype

Thuộc tính prototype là một thứ rất đặc biệt trong Javascript, có thể tìm hiểu thêm ở ĐÂY, ta sẽ sử dụng nó để tạo hàng loạt đối tượng giống nhau như sau:

function Fruit (_color, _name){
};

Fruit.prototype.color = 'general_color';
Fruit.prototype.name = 'general_name';
Fruit.prototype.showName = function(){
    console.log(this.name);
};

Với cách này thì ta cũng vẫn sẽ sử dụng hàm Fruit() để tạo ra các đối tượng object như cách ở trên:

var mangoFruit = new Fruit('yellow', 'Mango');
var appleFruit = new Fruit('red', 'Apple');

Thuộc tính prototype không chỉ được dùng duy nhất trong tình huống này. Do Javascript không phải là ngôn ngữ class-based (như PHP, C++, C#, …) mà là kiểu object-based, do đó chúng ta không thể thực hiện việc tạo class và kế thừa như các ngôn ngữ hướng đối tượng thuần tuý. Tuy nhiên, thuộc tính prototype cho phép ta thực hiện nhiều việc ‘tương tự’ như class và kế thừa trong Javascript, nhưng thôi, ta sẽ bàn chi tiết về nó ở một topic khác.

3. Một cái nhìn chi tiết hơn về Object

Ta biết rằng Object là kiểu dữ liệu phức hợp trong Javascript, bởi vì phức hợp nên nó sẽ có nhiều điều thú vị.

Kiểu dữ liệu tham trị và tham chiếu

Sự khác biệt cơ bản giữa kiểu dữ liệu tham trị và kiểu tham chiếu đó là: giá trị của kiểu dữ liệu tham chiếu không được lưu trực tiếp tại biến, mà biến đó sẽ lưu một tham chiếu tới giá trị thực.

Các kiểu dữ liệu cơ bản trong Javascript là các kiểu dữ liệu tham trị, còn kiểu dữ liệu Object sẽ là kiểu dữ liệu tham chiếu. Minh hoạ kiểu tham trị như sau:

//Kiểu dữ liệu cơ bản lưu giá trị thực sự (tham trị)
var num = 1;
var otherNum = num;             //bây giờ otherNum có giá trị là 1

//Thử thay đổi giá trị
num = 2;
console.log(num);               // 2
console.log(otherNum);          // 1

Như đã thấy ở trên, các kiểu dữ liệu cơ bản trong Javascript sẽ lưu giá trị theo kiểu tham trị. Ngược lại, kiểu dữ liệu Object sẽ lưu giá trị kiểu tham chiếu:

//Khai báo 2 đối tượng kiểu Object
var person = {name: "John"};
var otherPerson = person;

//Thử thay đổi giá trị
person.name = "Peter";
console.log(person.name);               //Peter
console.log(otherPerson.name);          //Peter

Như đã thấy, mặc dù thay đổi giá trị của biến ‘person’, nhưng giá trị của biến ‘otherPerson’ cũng bị thay đổi. Nguyên do của việc này là bởi các đối tượng Object lưu giá trị theo kiểu tham chiếu, tức là 2 biến này cùng tham chiếu tới 1 vùng giá trị.

Thuộc tính riêng và thuộc tính kế thừa của Object

Một cách khái quát, thuộc tính riêng (own property) là thuộc tính được định nghĩa tại bản thân của đối tượng (tại bản thân object), thuộc tính kế thừa (inherited property) là những thuộc tính được kế thừa từ đối tượng prototype của object đó. (Tới đây ta lại biết thêm được 1 tính chất nữa của prototype ^^)

Để kiểm tra một thuộc tính có thuộc object hay không (kể cả thuộc tính riêng và thuộc tính kế thừa), ta dùng toán tử in:

var school = {schoolName: 'Havard'};

//kiểm tra thuộc tính
console.log('schoolName' in school);     //true
console.log('schoolType' in school);     //false

Để kiểm tra một thuộc tính có phải là thuộc tính riêng hay không, ta có thể dùng phương thức hasOwnProperty của Object.

//tạo mẫu khởi tạo
function Fruit(){};
Fruit.prototype.color = 'general_color';

//tạo đối tượng và thuộc tính riêng
var apple = new Fruit();
apple.name = 'ownName';

//kiểm tra thuộc tính
console.log(apple.hasOwnProperty('color'));     //false
console.log(apple.hasOwnProperty('name'));      //true

Ta có thể nhận định thêm rằng, các thuộc tính định nghĩa trong prototype sẽ được kế thừa tới mọi object, nhưng ta vẫn có thể thêm các thuộc tính riêng cho từng object khác nhau. Đây là một trong những đặc điểm rất đặc biệt của thuộc tính prototype trong Javascript.

Các đặc tính của thuộc tính (Property Attributes)

Ta đã hiểu thế nào là các thuộc tính của object, bây giờ ta hãy xem xét chi tiết hơn về các đặc tính của nó.

Trong tiếng Anh, người ta gọi các thuộc tính là property, còn đặc tính thì được gọi là attribute. Một thuộc tính sẽ có 4 đặc tính sau đây:

  • Giá trị (value): Đây là đặc tính rõ thấy nhất, bởi vì mỗi thuộc tính đều mang 1 giá trị nào đó, có thể là giá trị cơ bản hoặc method.
  • Tính Enumable: mang giá trị true/false, cho phép một thuộc tính được duyệt qua trong vòng lặp for-in.
  • Tính configable: mang giá trị true/false, nói lên khả năng config như delete thuộc tính, thay đổi các đặc tính khác của thuộc tính, ...
  • Tính writable: mang giá trị true/false, cho phép ta thay đổi giá trị của thuộc tính hay không.

Nói một chút về việc xoá một thuộc tính của object, ta có thể dùng toán tử delete để xoá một thuộc tính của đối tượng. Để lệnh delete được thực thi, ta cần xoá đúng vị trí thuộc tính được định nghĩa, tức là: thuộc tính riêng thì xoá tại đối tượng, thuộc tính kế thừa thì xoá tại đối tượng prototype.

Hi vọng mọi người sẽ hiểu thêm nhiều thứ về Object trong Javascript. Thân!

vcttai 26-06-2017

Nguồn: Bàn về khái niệm Object trong Javascript

0