Các đối tượng thường được tạo để đại diện cho các thực thể của thế giới thực, như người dùng, đơn đặt hàng, v.v.

let user = {
  name: "David",
  age: 30
};

Và, trong thế giới thực, người dùng có thể hành động: chọn thứ gì đó từ giỏ hàng, đăng nhập, đăng xuất, v.v.

Các hành động được thể hiện bằng JavaScript bởi các hàm.

1. Ví dụ về phương thức(hàm)

Để bắt đầu, Ta có user nói xin chào:

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

let user = {
  name: "David",
  age: 30
};

user.sayHi = function() {
  alert("Hello!");
};

user.sayHi(); // Hello!

Ở đây chúng ta vừa sử dụng Biểu thức hàm để tạo hàm và gán nó cho thuộc tính user.sayHicủa đối tượng.

Sau đó chúng ta có thể gọi nó. Người dùng bây giờ có thể nói!

Một hàm là thuộc tính của một đối tượng được gọi là phương thức của nó .

Vì vậy, ở đây chúng ta đã có một phương thức sayHicủa đối tượng user.

Tất nhiên, chúng ta có thể sử dụng hàm được khai báo trước như một phương thức, như thế này:

-->
let user = {
  // ...
};

// first, declare
function sayHi() {
  alert("Hello!");
};

// then add as a method
user.sayHi = sayHi;

user.sayHi(); // Hello!

Lập trình hướng đối tượng

Khi chúng ta viết code bằng cách sử dụng các đối tượng để biểu diễn các thực thể, đó gọi là lập trình hướng đối tượng, nói ngắn gọn là:

OOP là một điều gì đó khá lớn. Làm thế nào để chọn đúng thực thể? Làm thế nào để tổ chức sự tương tác giữa chúng? Đó là kiến ​​trúc, và có những cuốn sách hay về chủ đề đó, như “Design Patterns: Elements of Reusable Object-Oriented Software” hoặc “Object-Oriented Analysis and Design with Applications” và nhiều hơn nữa.

Hoặc bạn có thể tham khảo phần Phần 8 trong series tự học C/C++ này.

2. Phương thức ngắn gọn

Tồn tại một cú pháp ngắn hơn cho các phương thức trong một đối tượng bằng chữ:

// these objects do the same

user = {
  sayHi: function() {
    alert("Hello");
  }
};

// method shorthand looks better, right?
user = {
  sayHi() { // same as "sayHi: function()"
    alert("Hello");
  }
};

Như đã chứng minh, chúng ta có thể bỏ qua "function"và chỉ viết sayHi().

Nói thật, các ký hiệu không hoàn toàn giống nhau. Có những khác biệt tinh tế liên quan đến kế thừa đối tượng (sẽ được đề cập sau), nhưng bây giờ chúng không quan trọng. Trong hầu hết các trường hợp, cú pháp ngắn hơn được ưa thích hơn.

3. “This” là một trong những phương thức

Điều phổ biến là một phương thức đối tượng cần truy cập vào thông tin được lưu trữ trong đối tượng để thực hiện công việc của nó.

Ví dụ, Code bên trong user.sayHi()có thể cần tên của user.

Để truy cập đối tượng, một phương thức có thể sử dụng từ khóa this

Giá trị của thislà một đối tượng, một đối tượng được sử dụng để gọi phương thức.

Ví dụ:

let user = {
  name: "John",
  age: 30,

  sayHi() {
    // "this" is the "current object"
    alert(this.name);
  }

};

user.sayHi(); // John

Ở đây trong quá trình thực hiện user.sayHi(), giá trị của thissẽ là user.

Về mặt kỹ thuật, bạn cũng có thể truy cập vào đối tượng mà không cần thistham chiếu thông qua biến ngoài:

let user = {
  name: "David",
  age: 30,

  sayHi() {
    alert(user.name); // "user" instead of "this"
  }

};

Nhưng code như vậy là không đáng tin cậy. Nếu chúng ta quyết định sao chép usersang một biến khác, ví dụ admin = uservà ghi đè userbằng thứ khác, thì nó sẽ truy cập sai đối tượng.

Điều đó đã được chứng minh dưới đây:

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

let user = {
  name: "David",
  age: 30,

  sayHi() {
    alert( user.name ); // leads to an error
  }

};


let admin = user;
user = null; // overwrite to make things obvious

admin.sayHi(); // Whoops! inside sayHi(), the old name is used! error!

Nếu chúng ta sử dụng this.namethay vì user.namebên trong alert, thì code sẽ hoạt động đúng.

4. “This” không phải là ràng buộc

Trong JavaScript, từ khóa thishoạt động không giống như hầu hết các ngôn ngữ lập trình khác. Nó có thể được sử dụng trong bất kỳ hàm nào.

Không có lỗi cú pháp trong ví dụ sau:

function sayHi() {
  alert( this.name );
}

Giá trị của thisđược đánh giá trong thời gian chạy, tùy thuộc vào ngữ cảnh.

Chẳng hạn, ở đây, cùng một hàm được gán cho hai đối tượng khác nhau, chúng ta sẽ thấy sự khác nhau khi gọi:

let user = { name: "David" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// use the same function in two objects
user.f = sayHi;
admin.f = sayHi;

// these calls have different this
// "this" inside the function is the object "before the dot"
user.f(); // John  (this == user)
admin.f(); // Admin  (this == admin)

admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)

Các quy tắc rất đơn giản: nếu obj.f()được gọi, sau đó thisobjtrong suốt gọi hàm f. Vì vậy, this là userhoặc admintrong ví dụ trên.

Gọi mà không có đối tượng: this == undefined

Chúng ta thậm chí có thể gọi hàm mà không cần một đối tượng nào cả:

function sayHi() {
  alert(this);
}

sayHi(); // undefined

Trong trường hợp thisnày là undefinedtrong chế độ nghiêm ngặt. Nếu chúng tôi cố gắng truy cập this.name, sẽ có một lỗi.

Trong chế độ không nghiêm ngặt, giá trị thistrong trường hợp đó sẽ là đối tượng toàn cục ( windowtrong trình duyệt, chúng ta sẽ tìm hiểu nó sau trong chương sau).

Thông thường cuộc gọi như vậy là một lỗi lập trình. Nếu có thisbên trong một hàm, nó sẽ được gọi trong một ngữ cảnh đối tượng.

Hậu quả của việc không ràng buộc this

Nếu bạn đến từ một ngôn ngữ lập trình khác, thì có lẽ bạn đã quen với ý tưởng về “ràng buộc this“, trong đó các phương thức được xác định trong một đối tượng luôn có thistham chiếu đến đối tượng đó.

Trong JavaScript thislà thoãi mái, giá trị của nó được đánh giá tại thời điểm khi gọi và không phụ thuộc vào nơi phương thức được khai báo, mà phụ thuộc vào đối tượng nào là trước khi chấm nó.

Ở đây, quan điểm của chúng ta là không đánh giá liệu quyết định thiết kế ngôn ngữ này là tốt hay xấu. Chúng ta sẽ hiểu cách làm việc với nó, làm thế nào để có được lợi ích và tránh các vấn đề.

5. Các hàm mũi tên không có “this”

Các hàm mũi tên rất đặc biệt: Nó không có this riêng. Nếu chúng ta tham chiếu thistừ một hàm như vậy, thì nó được lấy từ hàm bình thường bên ngoài.

Ví dụ, ở đây arrow()sử dụng thistừ user.sayHi()phương thức bên ngoài :

let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya

Đó là một tính năng đặc biệt của các hàm mũi tên, thật hữu ích khi chúng ta thực sự không muốn có một phần riêng biệt this, mà là để lấy nó từ bối cảnh bên ngoài. Ở phần sau của chương Các hàm mũi tên, chúng ta sẽ đi sâu hơn vào các hàm mũi tên.

6. Tóm lược

  • Các hàm được lưu trữ trong các thuộc tính đối tượng được gọi là các phương thức.
  • Các phương thức cho phép các đối tượng hành động như thế nào object.doSomething().
  • Các phương thức có thể tham chiếu đối tượng như this.

Giá trị của thisđược xác định tại thời gian chạy.

  • Khi một hàm được khai báo, nó có thể sử dụng this, nhưng nó thiskhông có giá trị cho đến khi hàm được gọi.
  • Một hàm có thể được sao chép giữa các đối tượng.
  • Khi một hàm được gọi là phương thức khi chúng ghi theo cú pháp sau:, object.method()giá trị của thistrong khi gọi là object.

Xin lưu ý rằng các hàm mũi tên là đặc biệt: chúng không có this. Khi thisđược truy cập bên trong một hàm mũi tên, nó được lấy từ bên ngoài.

Full series tự học Javascript từ cơ bản tới nâng cao tại đây nha.

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!