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.
Nội dung chính
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.sayHi
củ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 sayHi
củ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 this
là 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 this
sẽ 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 this
tham 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 user
sang một biến khác, ví dụ admin = user
và ghi đè user
bằ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.name
thay vì user.name
bê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 this
hoạ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 đó this
là obj
trong suốt gọi hàm f
. Vì vậy, this là user
hoặc admin
trong 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 this
này là undefined
trong 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ị this
trong trường hợp đó sẽ là đối tượng toàn cục ( window
trong 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ó this
bê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ó this
tham chiếu đến đối tượng đó.
Trong JavaScript this
là 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 this
từ 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 this
từ 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óthis
khô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ủathis
trong 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!