2012-04-04 44 views
9

Tôi đã đọc why it's betterhow it's implemented. Nhưng những gì tôi thực sự không hiểu là nó phá vỡ tham chiếu vòng tròn như thế nào?.Cách dữ liệu jQuery() ngắt tham chiếu vòng tròn

cách phá vỡ vòng kết nối tham chiếu?

$(div1).data('item', div2); 
$(div2).data('item', div1); 

như ví dụ, các điểm trên chỉ vào nhau, làm cách nào để ngăn chặn? Tôi có linh cảm, nhưng tôi chỉ muốn đảm bảo rằng linh cảm của tôi là đúng.

Trả lời

12

Sự cố tham chiếu vòng tròn xảy ra trong một số trình duyệt khi bạn đặt tham chiếu đến đối tượng DOM trên đối tượng DOM làm thuộc tính trên đối tượng DOM đó. Sau đó, bạn có hai đối tượng DOM trỏ vào nhau. Việc xóa một đối tượng DOM có thuộc tính tùy chỉnh trên nó sẽ không xóa thuộc tính tùy chỉnh đó. Một bộ thu gom rác không phải là thông minh không nhận ra rằng tham chiếu DOM này không được tính vì vậy nó bị kẹt và có một số cách mà điều này có thể dẫn đến rò rỉ.

.data() giải quyết vấn đề này vì dữ liệu .data() KHÔNG ở trên đối tượng DOM. Nó chỉ là một cấu trúc dữ liệu javascript có thể được liên kết với đối tượng DOM thông qua một ID chuỗi duy nhất.

Một khó hiểu một phần của việc này là khi bạn đọc với .data("key")key không được tìm thấy trong cấu trúc dữ liệu .data() javascript, sau đó và chỉ sau đó, jQuery sẽ tìm kiếm một thuộc tính trên đối tượng DOM gọi "data-key". Nhưng bất cứ khi nào bạn viết với .data("key", "myData"), nó không bao giờ ghi vào đối tượng DOM, chỉ với cấu trúc dữ liệu javascript.

Do đó, vì .data() không bao giờ ghi dữ liệu vào đối tượng DOM, nên không thể có bất kỳ loại tham chiếu vòng tròn nào mà một số trình duyệt gặp sự cố.

Có một số điều hữu ích khác cần biết về cấu trúc dữ liệu .data(). Khi bạn sử dụng số .remove() của jQuery để xóa các phần tử khỏi DOM hoặc khi bạn gọi $(elem).html("new html"), jQuery sẽ xóa dữ liệu .data() trên mọi mục đã xóa. Đây là một trong những trường hợp tốt để không kết hợp jQuery với javascript đơn giản. Nếu bạn đang sử dụng .data(), thì bạn luôn phải xóa các mục khỏi DOM bằng cách sử dụng các hàm jQuery để .data() được dọn dẹp một cách thích hợp. Nếu không, bạn có thể bị rò rỉ bộ nhớ theo cách này (cả hai dữ liệu .data() có thể bị rò rỉ và bất kỳ đối tượng DOM đã loại bỏ nào được tham chiếu trong .data() đều có thể bị rò rỉ.), sau đó jQuery sẽ làm sạch mọi thứ lên một cách thích hợp và sẽ không có rò rỉ

vì vậy, ví dụ, điều này sẽ tạo ra một rò rỉ bộ nhớ:.

// suppose elem is a DOM element reference 

// store some data in jQuery's data storage on behalf of a DOM element 
$(elem).data("someKey", "someValue"); 

// remove DOM element with plain Javascript 
elem.parentNode.removeChild(elem); 

Bởi vì bạn loại bỏ các phần tử với đồng bằng Javascript, jQuery DOM không có cơ hội dọn sạch dữ liệu bạn đã lưu trước đó. Bản thân phần tử DOM sẽ được thu thập rác, nhưng giá trị .data() mà bạn đã lưu trước đó màu đỏ bây giờ là mồ côi trong lưu trữ của jQuery và về cơ bản là một "rò rỉ" vì nó có khả năng sẽ không bao giờ bị xóa. Mặt khác, nếu bạn làm điều này:

$(elem).data("someKey", "someValue"); 
$(elem).remove(); 

Sau đó, jQuery sẽ thấy rằng bạn đang loại bỏ các phần tử DOM và cũng sẽ xóa dữ liệu bạn lưu trữ với .data().Một cách khá đơn giản để xem nó hoạt động như thế nào là tạo ra một kịch bản dòng đôi với một phiên bản không được tối thiểu hóa của jQuery và sau đó chỉ cần bước qua một cuộc gọi đến $(elem).data("key", "whatever") trong trình gỡ rối và xem nó hoạt động như thế nào.

+0

Bạn có thể minh họa lời giải thích của mình ở khoản 5 bằng ví dụ không? –

+0

@ techloris_109 - Đã thêm ví dụ. – jfriend00

Các vấn đề liên quan