Concept trung tâm của quá trình quản lý bộ nhớ ở trong JavaScript là tính có thể truy cập (reachability).
Các giá trị có thể truy cập là các giá trị mà có các tham chiếu đến nó. Các giá trị này được bảo đảm là sẽ không bị xóa ra khỏi vùng nhớ.
- Có một tập các giá trị có thể truy cập cố hữu và không thể bị xóa khỏi vùng nhớ bởi nhiều lý do. Ví dụ:
- Hàm đang thực thi, các biến cục bộ và các tham số của nó.
- Các biến toàn cục.
- Các giá trị khác được xem là có thể truy cập nếu nó có ít nhất một tham chiếu hoặc một chuỗi các tham chiếu đến từ một biến toàn cục.
Garbage collector là một tiến trình chạy nền của JS engine giúp theo dõi và loại bỏ các object không thể truy cập.
Example
Xét ví dụ sau:
// `user` has a reference to the object
let user = {
name: "John",
}Trong đoạn code trên, biến toàn cục user tham chiếu đến đối tượng {name: "John"} (ta gọi là John cho ngắn gọn).
Nếu giá trị của user bị ghi đè, tham chiếu đến John sẽ bị mất.
user = nullKhi đó, John sẽ trở nên unreachable (không thể truy cập). Dẫn đến, garbage collector sẽ xóa bỏ dữ liệu và giải phóng vùng nhớ của John.
Two References
Xét trường hợp ta sao chép tham chiếu của user cho admin:
// `user` has a reference to the object
let user = {
name: "John",
}
let admin = userKhi đó, nếu ta chỉ ghi đè giá trị của user thì John vẫn còn một tham chiếu đến từ admin và do đó nó sẽ không bị xóa bỏ khỏi vùng nhớ.
Chỉ khi nào ta ghi đè luôn cả giá trị của admin thì John mới bị xóa bỏ khỏi vùng nhớ
Interlinked Objects
Xét một ví dụ phức tạp hơn:
function marry(man, woman) {
woman.husband = man
man.wife = woman
return {
father: man,
mother: woman,
}
}
let family = marry(
{
name: "John",
},
{
name: "Ann",
},
)Trong đoạn code trên, hàm marry sẽ liên kết hai đối tượng truyền vào (man và woman) bằng cách cho chúng tham chiếu lẫn nhau và sau đó trả về một đối tượng chứa hai đối tượng đó ({father: man, mother: woman}).
Lúc này, tất cả các object đều có thể truy cập. Nếu ta xóa hai tham chiếu đến đối tượng John:
delete family.father
delete family.mother.husbandThì John sẽ trở nên unreachable do không còn đối tượng nào tham chiếu đến nó nữa và nó sẽ bị xóa bỏ.
Note
Lưu ý là ta chỉ xét incoming reference chứ không xét outcoming reference.
Unreachable Island
Có thể có khả năng toàn bộ các interlinked object trở nên unreachable và bị xóa khỏi vùng nhớ.
Giả sử xét biến family như ở trên. Ta thực hiện ghi đè giá trị của nó:
family = nullKhi đó, John và Ann vẫn còn liên kết với nhau và đều được tham chiếu bởi một object khác, ta tạm gọi là Parent. Tuy nhiên, biến family (là một biến toàn cục) không còn tham chiếu đến Parent và do đó toàn bộ ba object không còn có thể truy cập được nên chúng sẽ bị xóa khỏi vùng nhớ.
Important
Như vậy, nếu một object và các object con của nó bị mất tham chiếu từ một global object thì nó sẽ trở nên unreachable và sẽ bị garbage collector xóa bỏ.
Internal Algorithms
Thuật toán thu hồi rác cơ bản có tên là “mark and sweep”. Các bước thực hiện của nó như sau:
- Duyệt và đánh dấu các object được reference bởi các biến toàn cục.
- Duyệt và đánh dấu các object được reference bởi các object đã được đánh dấu. Tất cả các object đã được duyệt đều sẽ được ghi nhớ để tránh trường hợp duyệt một object hai lần.
- Tất cả các object không được đánh dấu thì sẽ bị xóa bỏ.
Quá trình trên sẽ được thực hiện một cách tự động bởi garbage collector.