Nguyên nhân chính gây ra rò rỉ trong các ngôn ngữ được thu thập rác là các tham chiếu không mong muốn. Để hiểu rò rỉ bộ nhớ, hãy xem cách giải phóng bộ nhớ (thu gom rác) hoạt động như thế nào.
Thuật toán đánh dấu và quét − Thuật toán này giảm định nghĩa "một đối tượng không còn cần thiết" thành "một đối tượng không thể truy cập được". Thuật toán này giả định kiến thức của một tập hợp các đối tượng được gọi là gốc. Trong JavaScript, gốc là đối tượng toàn cục. Định kỳ, GC bắt đầu từ các gốc này, tìm tất cả các đối tượng được tham chiếu từ các gốc này, một cách đệ quy. Bắt đầu từ gốc, GC do đó sẽ tìm tất cả các đối tượng có thể truy cập và thu thập tất cả các đối tượng không thể truy cập.
Các loại rò rỉ bộ nhớ
1. Biến toàn cục (không được khai báo / tình cờ)
Trong JS, bạn có thể vô tình khai báo một biến trên toàn cầu nếu bạn không chỉ định từ khóa khai báo (let, var, const). JS tìm kiếm việc di chuyển ra khỏi phạm vi cho đến khi nó đạt đến phạm vi toàn cầu và nếu nó không tìm thấy biến trong bất kỳ phạm vi nào, nó sẽ tạo ra một biến toàn cục.
Ví dụ
function test() { a = [1, 2, 3] } test() // a was initialized without declaration using a keyword and is now in the global scope. console.log(a)
Đầu ra
[1, 2, 3]
Hành vi này có thể gây ra rò rỉ bộ nhớ vì các biến vô tình hiện diện trong phạm vi toàn cục và sẽ không được giải phóng trừ khi chương trình kết thúc. Điều này có thể được khắc phục bằng cách sử dụng từ khóa khai báo.
2. Đóng cửa
Rò rỉ bộ nhớ xảy ra trong một bao đóng nếu một biến được khai báo trong hàm bên ngoài và biến đó tự động trở nên khả dụng cho hàm bên trong lồng nhau và tiếp tục ở trong bộ nhớ ngay cả khi nó không được sử dụng / tham chiếu trong hàm lồng nhau.
3. DOM được tách rời / Tham chiếu ngoài DOM
DOM là một cây được liên kết kép, có tham chiếu đến bất kỳ nút nào trong cây sẽ ngăn toàn bộ cây thu thập rác. Tham chiếu DOM được tách rời hoặc Out of DOM có nghĩa là các nút đã bị xóa khỏi DOM nhưng nằm trong bộ nhớ thông qua JS. Điều đó có nghĩa là miễn là vẫn còn tham chiếu đến một biến hoặc một đối tượng ở bất kỳ đâu, thì đối tượng đó sẽ không bị thu thập rác ngay cả sau khi bị xóa khỏi DOM. Luôn xóa tham chiếu khỏi JS sau khi bạn hoàn thành một phần của DOM.
4. Người nghe sự kiện
Phương thức addEventListener () gắn một trình xử lý sự kiện vào một phần tử và nhiều trình xử lý sự kiện có thể được thêm vào một phần tử. Nếu một phần tử DOM và trình xử lý sự kiện của nó không có cùng vòng đời, điều đó có thể dẫn đến rò rỉ bộ nhớ.