2009-08-28 34 views
12

Tôi đang viết một ứng dụng web có phần "vỏ" bên ngoài tĩnh và phần nội dung động. Phần nội dung động có nhiều cập nhật khi người dùng điều hướng hệ thống. Khi một khối nội dung mới được tải, nó cũng có thể tùy chọn tải một tệp JavaScript khác. Trong tên của dịch vụ dọn dẹp tốt, tôi xóa các khối tập lệnh khỏi DOM áp dụng cho các khối nội dung cũ, vì JavaScript đó không còn cần thiết nữa.Có thể tải JavaScript tự động không?

Sự cố xảy ra tiếp theo, khi tôi nhận ra rằng mặc dù tôi đã xóa phần tử <script> khỏi DOM, JavaScript đã được đánh giá trước đó vẫn có sẵn để thực thi. Điều đó có ý nghĩa tất nhiên, nhưng tôi lo lắng rằng nó có thể gây ra rò rỉ bộ nhớ nếu người dùng điều hướng đến nhiều phần khác nhau.

Câu hỏi sau đó, tôi có nên lo lắng về tình huống này không? Nếu vậy, có cách nào để buộc trình duyệt dọn dẹp JavaScript cũ?

Trả lời

14

<theory> Bạn có thể đi với một cách tiếp cận hướng đối tượng hơn và xây dựng mô hình theo cách mà mỗi khối khối javascript đến như là các đối tượng của riêng chúng, với các phương pháp riêng của chúng. Khi dỡ nó, bạn chỉ cần đặt đối tượng đó thành null. </theory>

3

Nếu bạn lưu mã đánh giá trong không gian tên, chẳng hạn như:

var MYAPP = { 
    myFunc: function(a) { ... } 
} 

"Giải phóng" toàn bộ điều nên càng đơn giản như thiết MYPP đối với một số giá trị ngẫu nhiên, ala

MYAPP = 1 

Điều này phụ thuộc vào việc không có phương tiện tham chiếu biến nào khác, không phải là tầm thường

+2

Tại sao không xóa MYAPP hoặc MYAPP = không xác định? – Dykam

+0

Không chỉ bản thân biến, mà còn bất kỳ bao đóng nào có thể được tạo ra là các hàm bên trong. – txwikinger

+0

@txwinker: Vâng, tôi đoán tôi cảm thấy điều đó được ngụ ý. Để làm việc này, không được có tham chiếu đến cả MYAPP lẫn bất cứ thứ gì bên trong nó. Và có một số chi tiết khó tính khi nói đến rò rỉ bộ nhớ và IE. @ Dykam: Không có lý do để không đi không xác định, nhưng tôi tránh xóa, vì tôi không có nhiều kinh nghiệm với nó, và "1" không nên đặt một sự căng thẳng bộ nhớ lớn trên bất cứ điều gì OP có thể làm. – Svend

1

Làm cách nào để tải các tệp JS vào khung nội tuyến? Sau đó (trên lý thuyết, không bao giờ thử nghiệm nó bản thân mình), bạn có thể loại bỏ các khung nội tuyến từ DOM và loại bỏ các "bộ nhớ" nó sử dụng.

Tôi nghĩ ... hay tôi hy vọng ...

1

Nếu bạn đang lo lắng về rò rỉ bộ nhớ sau đó bạn sẽ muốn chắc chắn rằng không có xử lý sự kiện trong các mã mà bạn muốn remove đề cập đến vẫn còn tồn tại cây dom.

Có thể bạn cần giữ một danh sách tất cả các trình xử lý sự kiện mà mã của bạn đã thêm vào và trước khi dỡ, đi qua và xóa trình xử lý sự kiện.

Tôi chưa bao giờ thực hiện theo cách đó, tôi luôn lo lắng khi tôi xóa các nút vẫn còn tham chiếu.

Đây là một bài viết tốt về javascript bộ nhớ bị rò rỉ: http://javascript.crockford.com/memory/leak.html

9

(này được khá off-the-cuff.)

sử dụng bộ nhớ thực sự là một vấn đề bạn cần phải quan tâm đến việc trong hiện tại trình duyệt của nhà nước của nghệ thuật, mặc dù trừ khi chúng tôi đang nói về khá nhiều mã, tôi không biết rằng kích thước mã là vấn đề (nó thường là kích thước DOM, và xử lý sự kiện còn sót lại).

Bạn có thể sử dụng mẫu cho các mô-đun có thể tải để dễ dàng tải chúng xuống hàng loạt - hoặc ít nhất, để cho trình duyệt biết rằng có thể dỡ chúng.

xem xét:

window.MyModule = (function() { 

    alert('This happens the moment the module is loaded.'); 

    function MyModule() { 

     function foo() { 
      bar(); 
     } 

     function bar() { 
     } 

    } 

    return MyModule; 
})(); 

Đó định nghĩa một kết thúc có chứa các chức năng foobar, có thể gọi nhau theo cách thông thường. Lưu ý rằng mã bên ngoài chức năng chạy ngay lập tức.

Miễn là bạn không đưa ra bất kỳ tham chiếu nào về nội dung bên trong đóng bất kỳ thứ gì bên ngoài nó, sau đó window.MyModule sẽ là tham chiếu duy nhất cho việc đóng và ngữ cảnh thực thi của nó. Để hủy tải xuống:

try { 
    delete window.MyModule; 
} 
catch (e) { 
    // Work around IE bug that doesn't allow `delete` on `window` properties 
    window.MyModule = undefined; 
} 

Điều đó cho môi trường JavaScript bạn không sử dụng thuộc tính đó nữa và làm cho mọi thứ tham chiếu có sẵn để thu thập rác. Khi nào và liệu bộ sưu tập đó có xảy ra rõ ràng là phụ thuộc vào việc triển khai thực hiện hay không.

Lưu ý rằng nó sẽ rất quan trọng nếu bạn móc trình xử lý sự kiện trong mô-đun để hủy chúng trước khi dỡ. Bạn có thể làm điều đó bằng cách trả lại một tham chiếu đến một hàm destructor thay vì việc đóng cửa chính:

window.MyModule = (function() { 

    alert('This happens the moment the module is loaded.'); 

    function foo() { 
     bar(); 
    } 

    function bar() { 
    } 

    function destructor() { 
     // Unhook event handlers here 
    } 

    return destructor; 
})(); 

unhooking là sau đó:

if (window.MyModule) { 
    try { 
     window.MyModule(); 
    } 
    catch (e) { 
    } 
    try { 
     delete window.MyModule; 
    } 
    catch (e) { 
     // Work around IE bug that doesn't allow `delete` on `window` properties 
     window.MyModule = undefined; 
    } 
} 
0

Javascript dịch viên có thu gom rác thải. Nói cách khác, nếu bạn không tham khảo bất cứ điều gì, nó sẽ không giữ chúng xung quanh.

Một trong những lý do tại sao việc sử dụng JSON với chức năng gọi lại (JSONP) là tốt.

Ví dụ, nếu bạn HTTP phản ứng đối với từng JS là:

callback({status: '1', resp: [resp here..]}); 

Và nếu callback() không tạo ra một tham chiếu đến đối tượng JSON thông qua tại như một cuộc tranh cãi, nó sẽ được thu gom rác sau khi chức năng hoàn thành.

Nếu bạn thực sự cần tham khảo, bạn có thể cần dữ liệu đó xung quanh vì một số lý do - nếu không bạn sẽ KHÔNG nên tham chiếu nó ngay từ đầu.

Các phương pháp được đề cập đến đối tượng không gian tên chỉ tạo tham chiếu sẽ được duy trì cho đến khi số tham chiếu đến 0. Nói cách khác, bạn phải theo dõi mọi tham chiếu và xóa nó sau này, có thể khó khăn khi bạn đóng và các tham chiếu từ DOM nằm xung quanh. Chỉ một tham chiếu sẽ giữ đối tượng trong bộ nhớ và một số thao tác đơn giản có thể tạo tham chiếu mà bạn không nhận ra nó.

0

Thảo luận hay. Xóa rất nhiều thứ. Tôi có một lo lắng, mặc dù.

Nếu tôi ràng buộc cửa sổ.MyModule.bar() vào một sự kiện, điều gì sẽ xảy ra nếu sự kiện vô tình bị kích hoạt sau khi window.MyModule bị xóa? Đối với tôi, toàn bộ điểm của việc đặt tên và tách các js thành các mô-đun được nạp động là tránh kích hoạt các trình xử lý sự kiện xuyên mô-đun do nhầm lẫn.

Ví dụ, nếu tôi làm (tha jQuery của tôi):

$ (' một số hạng nhất.) Bấm (window.MyModule.bar);.

Điều gì sẽ xảy ra nếu tôi xóa cửa sổ.MyModule, tải mô-đun khác và nhấp vào yếu tố vô tình có lớp được gọi là một số lớp?

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