Các lớp tích hợp như Array, Map và các lớp khác cũng có thể mở rộng.
Chẳng hạn, ở đây PowerArray
kế thừa từ nguồn gốc Array
:
/*
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/
*/
// add one more method to it (can do more)
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}
}
let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false
let filteredArr = arr.filter(item => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false
Xin lưu ý một điều rất thú vị. Phương thức như filter
, map
và những phương thức khác – trả về đối tượng mới chính là loại di truyền củaPowerArray
(có kiểu PowerArray
). Việc thực hiện nội bộ của họ sử dụng thuộc tínhconstructor
của đối tượng cho điều đó.
Trong ví dụ trên,
arr.constructor === PowerArray
Khi hàmarr.filter()
được gọi, bên trong nó tạo ra mảng kết quả mới bằng cách sử dụng chính xác arr.constructor
. Điều đó thực sự rất tuyệt, bởi vì chúng ta có thể tiếp tục sử dụng các phương thức của PowerArray
hơn nữa về kết quả.
Thậm chí nhiều hơn, chúng ta có thể tùy chỉnh hành vi đó.
Chúng ta có thể thêm một getter tĩnh đặc biệt Symbol.species
cho lớp. Nếu nó tồn tại, nó sẽ trả về hàm tạo mà JavaScript sẽ sử dụng bên trong để tạo các thực thể mới map
, filter
v.v.
Nếu chúng ta muốn xây dựng trong các phương thức như map
hoặc filter
trở về mảng thông thường, chúng ta có thể trở lại Array
trong Symbol.species
, giống như ở đây:
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}
// built-in methods will use this as the constructor
static get [Symbol.species]() {
return Array;
}
}
let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false
// filter creates new array using arr.constructor[Symbol.species] as constructor
let filteredArr = arr.filter(item => item >= 10);
// filteredArr is not PowerArray, but Array
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
Như bạn có thể thấy, bây giờ .filter
trả lại Array
. Vì vậy, hàm mở rộng không được thông qua nữa.
Các bộ sưu tập khác hoạt động tương tự
Các bộ sưu tập khác, như Map
và Set
, hoạt động như nhau. Họ cũng sử dụng Symbol.species
.
1. Không có kế thừa tĩnh trong đối tượng tích hợp
Các đối tượng tích hợp sẵn có các phương thức tĩnh riêng Object.keys
, Array.isArray
v.v.
Như chúng ta đã biết, các lớp bản địa mở rộng lẫn nhau. Ví dụ, Array
mở rộng Object
.
Thông thường, khi một lớp mở rộng lớp khác, cả hai phương thức tĩnh và không tĩnh đều được kế thừa. Điều đó đã được giải thích kỹ lưỡng trong bài viết Thuộc tính và phương pháp tĩnh.
Nhưng các lớp tích hợp là một ngoại lệ. Họ không kế thừa thống kê lẫn nhau.
Ví dụ, cả hai Array
và Date
kế thừa từ Object
, vì vậy các thể hiện của chúng có các phương thức từ Object.prototype
. Nhưng Array.[[Prototype]]
không tham chiếu Object
, vì vậy, không có kế thừa được, ví dụ, phương thức tĩnhArray.keys()
(hoặc Date.keys()
) .
Đây là cấu trúc hình ảnh cho Date
và Object
:
Như bạn có thể thấy, không có liên kết giữa Date
và Object
. Họ là độc lập, chỉ Date.prototype
thừa kế từ Object.prototype
.
Đó là một sự khác biệt quan trọng của sự kế thừa giữa các đối tượng tích hợp so với những gì chúng ta có được extends
.
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!