Câu trả lời:
JavaScript đơn giản
Nếu một phần tử DOM bị loại bỏ không có tham chiếu (không có tham chiếu trỏ đến nó) thì có - phần tử được chọn bởi trình thu gom rác cũng như bất kỳ trình xử lý / trình lắng nghe sự kiện nào liên quan đến nó.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
b = null;
// A reference to 'b' no longer exists
// Therefore the element and any event listeners attached to it are removed.
Tuy nhiên; nếu có các tham chiếu vẫn trỏ đến phần tử đã nói, phần tử và phần tử lắng nghe sự kiện của nó được giữ lại trong bộ nhớ.
var a = document.createElement('div');
var b = document.createElement('p');
// Add event listeners to b etc...
a.appendChild(b);
a.removeChild(b);
// A reference to 'b' still exists
// Therefore the element and any associated event listeners are still retained.
jQuery
Sẽ công bằng khi giả định rằng các phương thức có liên quan trong jQuery (chẳng hạn như remove()
) sẽ hoạt động theo cùng một cách chính xác (xem xét remove()
được viết bằng cách sử dụng removeChild()
chẳng hạn).
Tuy nhiên, điều này không đúng ; thư viện jQuery thực sự có một phương thức bên trong (không có tài liệu và về lý thuyết có thể thay đổi bất cứ lúc nào) được gọi cleanData()
(đây là phương thức này trông như thế nào ) tự động dọn sạch tất cả dữ liệu / sự kiện liên quan đến một phần tử khi xóa khỏi DOM (được điều này thông qua. remove()
, empty()
, html("")
vv).
Các trình duyệt cũ hơn - cụ thể là các phiên bản IE cũ hơn - được biết là có vấn đề rò rỉ bộ nhớ do người nghe sự kiện giữ các tham chiếu đến các yếu tố mà chúng được đính kèm.
Nếu bạn muốn giải thích sâu hơn về nguyên nhân, mẫu và giải pháp được sử dụng để khắc phục rò rỉ bộ nhớ phiên bản IE cũ, tôi hoàn toàn khuyên bạn nên đọc bài viết MSDN này về Tìm hiểu và Giải quyết các mẫu rò rỉ Internet Explorer.
Một vài bài viết liên quan đến điều này:
Tự mình loại bỏ người nghe có lẽ sẽ là một thói quen tốt trong trường hợp này (chỉ khi bộ nhớ là quan trọng đối với ứng dụng của bạn và bạn thực sự đang nhắm mục tiêu các trình duyệt như vậy).
remove
phương thức. hầu hết thời gian DOM sẽ bị xóa hoàn toàn. (như liên kết turbo hoặc một cái gì đó). Tôi tự hỏi bộ nhớ bị ảnh hưởng như thế nào nếu tôi làm document.body.innerHTML = ''
...
liên quan đến jQuery:
phương thức .remove () lấy các phần tử ra khỏi DOM. Sử dụng .remove () khi bạn muốn loại bỏ phần tử đó, cũng như mọi thứ bên trong nó. Ngoài các phần tử, tất cả các sự kiện bị ràng buộc và dữ liệu jQuery liên quan đến các phần tử được loại bỏ. Để xóa các phần tử mà không xóa dữ liệu và sự kiện, hãy sử dụng .detach () để thay thế.
Tham khảo: http://api.jquery.com/remove/
.remove()
Mã nguồn jQuery v1.8.2 :
remove: function( selector, keepData ) {
var elem,
i = 0;
for ( ; (elem = this[i]) != null; i++ ) {
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
if ( !keepData && elem.nodeType === 1 ) {
jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );
}
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
}
return this;
}
rõ ràng jQuery sử dụng node.removeChild()
Theo đó: https://developer.mozilla.org/en-US/docs/DOM/Node.removeChild ,
The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.
tức là người nghe sự kiện có thể bị xóa, nhưng node
vẫn tồn tại trong bộ nhớ.
removeChild
như vậy. Cả hai cũng trả về cho bạn một tham chiếu mà bạn có thể giữ lại để gắn lại sau này (trong trường hợp đó rõ ràng nó vẫn còn trong bộ nhớ) hoặc cách ném (trong trường hợp đó cuối cùng nó được chọn bởi GC và loại bỏ).
Đừng ngần ngại xem heap để xem rò rỉ bộ nhớ trong các trình xử lý sự kiện giữ tham chiếu đến phần tử với phần đóng và phần tử giữ tham chiếu đến trình xử lý sự kiện.
Người thu gom rác không thích tài liệu tham khảo vòng tròn.
Trường hợp rò rỉ bộ nhớ thông thường: thừa nhận một đối tượng có tham chiếu đến một phần tử. Yếu tố đó có một ref cho người xử lý. Và xử lý có một ref cho đối tượng. Đối tượng có ref cho rất nhiều đối tượng khác. Đối tượng này là một phần của bộ sưu tập mà bạn nghĩ rằng bạn đã vứt bỏ bằng cách hủy bỏ nó khỏi bộ sưu tập của bạn. => toàn bộ đối tượng và tất cả những gì nó đề cập sẽ vẫn còn trong bộ nhớ cho đến khi thoát khỏi trang. => bạn phải suy nghĩ về một phương thức tiêu diệt hoàn toàn cho lớp đối tượng của bạn hoặc tin tưởng vào khung mvc chẳng hạn.
Hơn nữa, đừng ngần ngại sử dụng phần Cây giữ lại của các công cụ phát triển Chrome.
Chỉ cần mở rộng câu trả lời khác ...
Trình xử lý sự kiện được ủy nhiệm sẽ không bị xóa khi xóa phần tử.
$('body').on('click', '#someEl', function (event){
console.log(event);
});
$('#someEL').remove(); // removing the element from DOM
Kiểm tra bây giờ:
$._data(document.body, 'events');
Về jQuery
các phương thức phổ biến sau đây cũng sẽ loại bỏ các cấu trúc khác như xử lý dữ liệu và sự kiện:
Ngoài các phần tử, tất cả các sự kiện bị ràng buộc và dữ liệu jQuery liên quan đến các phần tử được loại bỏ.
Để tránh rò rỉ bộ nhớ, jQuery loại bỏ các cấu trúc khác như xử lý dữ liệu và sự kiện khỏi các phần tử con trước khi tự loại bỏ các phần tử.
Ngoài ra, jQuery loại bỏ các cấu trúc khác như xử lý dữ liệu và sự kiện khỏi các phần tử con trước khi thay thế các phần tử đó bằng nội dung mới.
Có, người thu gom rác cũng sẽ loại bỏ chúng. Có thể không phải luôn luôn là trường hợp với các trình duyệt cũ.