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

       Trong Javascript, một trong những khái niệm cốt lõi và cơ bản nhất của nó là khái niệm về Object, đây cũng chính là một kiểu dữ liệu trong JS – kiểu dữ liệu Object. Bạn cần hiểu được và nắm vững các khái niệm cơ bản của Js trước khi có ý định học các Framework của nó.

     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.

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

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ó. Có những trò khá vui vẻ với this, bạn có thể xem qua.

Sử dụng prototype

     Thuộc tính prototype là một thứ rất đặc biệt trong Javascript, ta sẽ bàn về nó sau, ở đâ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.

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 được lưu trữ như là “một tham chiếu”, tức là giá trị của biến sẽ 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 giá trị, thay đổi giá trị này sẽ thay đổi giá trị thuộc tính của tất cả những đối tượng khác đang tham chiếu tới nó.

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
var apple = new Fruit();
//tạo thuộc tính riêng của object
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

     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.

     Nắm rõ được khái niệm Object trong Javascript, ta đã đủ cơ sở để có thể tìm hiểu được một trong những khái niệm lắt léo nhất của Javascript, đó là khái niệm Prototype. Topic tới sẽ bàn về chủ đề này nhé. Xin cảm ơn.

3 thoughts on “[ Javascript ] Bàn về khái niệm Object trong Javascript.

  1. Thanh Tac

    Góp ý: “var otherNum = num; //bây giờ otherNum có giá trị là 2” chỗ này giá trị otherNum phải là 1 mới đúng 😀

    Like

  2. Pingback: [ Javascript ] Prototype trong Javascript là gì, và tại sao nó lại quan trọng? – Những dòng code vui

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s