Bài viết được sự cho phép của tác giả Lưu Bình An
Khi chúng ta console.log
một object của JS, sẽ thấy một property ẩn đặc biệt [[Prototype]]
, nó có thể là null
hoặc là trỏ đến một object khác
object a => [[Prototype]] => prototype object b
Điều này có nghĩa là object a kế thừa từ object b, b có gì thì a sẽ có đó
Xem thêm nhiều việc làm JavaScript hấp dẫn trên TopDev
Chúng ta không thể truy xuất trực tiếp thông qua [[Prototype]]
, mà thông qua các phương pháp khác
let animal = {
eats: true,
walk() {
alert("Animal walk");
}
}
let rabbit = {
jumps: true,
__proto__: animal}
// hoặc khai báo bằng
rabbit.__proto__ = animal;
console.log(rabbit.eats);
// => true;
rabbit.walk();
__proto__
!=[[Prototype]]
Về bản chất, __proto__
không phải là property [[Prototype]]
, chính xác thì nó là getter/setter của [[Prototype]]
Thời điểm hiện tại, không khuyến khích dùng __proto__
, thay vào đó dùng Object.getPrototypeOf/Object.setPrototypeOf
let user = {
name: "John",
surname: "Smith",
set fullName(value) {
[this.name, this.surname] = value.split(" ");
},
get fullName() {
return `${this.name} ${this.surname}`;
}
}
let admin = {
__proto__: user,
isAdmin: true
}
alert(admin.fullName);
// => John Smith
admin.fullName = "Alice Cooper";
alert(admin.fullName);// => Alice Cooper
alert(user.fullName);// => John Smith
Khi dùng prototype, không trực tiếp thay đổi property ở object cha từ object con, việc này cần thông qua một hàm setter để đảm bảo dữ liệu sẽ độc lập trên từng object.
Như ví dụ trên, this
lúc này đang trỏ đến object phía trước dấu .
, nên dữ liệu hoàn toàn độc lập, trong khi các phương thức thì share với nhau
Vòng lặp for...in
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
alert(Object.keys(rabbit));// jumps
for(let prop in rabbit) alert(prop); // jumps, then eats
Nếu không muốn chạy qua các property
kề thừa qua __prototype__
, sử dụng obj.hasOwnProperty(key)
để xác định 1 property của được kế thừa hay không
for(let prop in rabbit) {
let isOwn = rabbit.hasOwnProperty(prop);
if (isOwn) {
alert(`Our: ${prop}`);
// Our: jumps
} else {
alert(`Inherited: ${prop}`);
// Inherited: eats
}
}
Một điều thú vị, nếu để ý chúng ta không hề khai báo rabbit.hasOwnProperty
, vậy nó từ đâu mà có? và nó cũng không xuất hiện bên trong vòng lặp for...in
?
Đây là một property kế thừa từ Object
chúa, và nó đã được khai báo decriptor với giá trị enumerable: false
Đọc lại bài decriptor
Tóm tắt
- Mỗi object sẽ chứa một property đặc biệt
[[Prototype]]
, giá trị là null, hoặc trỏ đến một object khác - Sử dụng
obj.__proto__
để truy cập this
luôn trỏ đến obj hiện tại thay vì prototype objectfor..in
sẽ chạy qua tất cả property chính chủ và property được kế thừa
Bài viết gốc được đăng tải tại vuilaptrinh.com
Có thể bạn quan tâm:
- Javascript Prototype là gì?
- Vượt qua các bài phỏng vấn Javascript
- 5 cách chia một mảng lớn thành nhiều mảng nhỏ trong Javascript
Xem thêm Việc làm IT hấp dẫn trên TopDev