2009-08-28 7 views
12

静的な外側の「シェル」と動的コンテンツセクションを持つWebアプリケーションを作成しています。動的コンテンツセクションには、ユーザーがシステムをナビゲートする際に多くの更新があります。新しいコンテンツブロックが読み込まれると、別のJavaScriptファイルを読み込むこともできます。適切なハウスキーピングの名前で、古いコンテンツブロックに適用されるDOMからスクリプトブロックを削除します。これはJavaScriptが不要になったためです。JavaScriptを動的に読み込むことができますか?

DOMから<script>要素を削除したにもかかわらず、以前に評価されたJavaScriptがまだ実行可能であることを認識したとき、次に問題が発生します。それはもちろん意味がありますが、ユーザーが多くの異なるセクションに移動するとメモリリークが発生する可能性があることを心配しています。

質問がありましたら、私はこの状況を心配すべきですか?もしそうなら、古いブラウザを強制的にクリーンアップする方法がありますか?

答えて

14

<theory>もっとオブジェクト指向のアプローチで、独自のメソッドを使って、javascriptブロックの各ブロックが独自のオブジェクトとして入るようにモデルを構築することができます。アンロードする際には、そのオブジェクトをnullに設定するだけです。 </theory>

3

次のような名前空間では、評価コード、保存した場合:

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

を全部は

MYAPP = 1 

たala、いくつかのランダムな値にMYPPを設定するのと同じくらい簡単でなければなりません「解放」これは、変数を参照する他の手段がないことに依存します。これは簡単ではありません。

+2

MYAPPまたはMYAPP =未定義を削除しないのはなぜですか? – Dykam

+0

変数そのものだけでなく、作成される可能性のあるクロージャも内部の関数です。 – txwikinger

+0

@txwinker:はい、私はそれが暗示されたと感じたと思います。これが機能するためには、MYAPPもその内部のものも参照してはいけません。そして、メモリやIEが漏れてくると、細かいところがあります。 @Dykam:未定義ではない理由はありませんが、私はそれに多くの経験を持っていないので、削除を避けました。 "1"は、OPが何をしているのかに大きな記憶をかけるべきではありません。 – Svend

1

JSファイルをiframeに読み込む方法はありますか?その後、(理論的には、自分でそれをテストしたことはありません)DOMからiframeを削除し、それが使っている "メモリ"を削除することができます。

私が思う...または私は願っています...

1

あなたはメモリリークを心配しているなら、あなたはまだ、既存に言及削除するコードには、イベントハンドラが存在しないことを確信したいでしょうドームツリー。

コードが追加されたすべてのイベントハンドラのリストを保持し、アンロードする前にイベントハンドラを通過して削除する必要がある場合があります。

私はそれをやったことがない、私はいつも参照があるノードを削除するときに心配します。ここで

は、JavaScriptのメモリリークの良い記事です: http://javascript.crockford.com/memory/leak.html

9

(これはかなりオフカフである。)

メモリの使用が実際にあなたが現在ではと心配する必要が問題ですブラウザの最先端のものですが、非常に多くのコードについて話していない限り、コードサイズが問題であることはわかりません(通常はDOMサイズ、残ったイベントハンドラ)。

ロード可能なモジュールのパターンを使用すると、ブロックをアンロードするのがはるかに簡単になります。少なくとも、ブラウザにはがあります。はアンロードできます。

は検討:

window.MyModule = (function() { 

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

    function MyModule() { 

     function foo() { 
      bar(); 
     } 

     function bar() { 
     } 

    } 

    return MyModule; 
})(); 

は通常の方法で互いを呼び出すことができる関数foobarを含有クロージャを定義します。関数外のコードはすぐに実行されることに注意してください。

閉鎖内のものへの参照をその外側のものに渡さないと、window.MyModuleはその閉包とその実行コンテキストへの唯一の参照になります。それをアンロードするには:あなたはもうそのプロパティを使用していないJavaScript環境を伝え、それがガベージコレクションのために参照可能なものを作る

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

を。そのコレクションが発生するかどうかは明らかに実装に依存します。

イベントハンドラをモジュール内でフックしてアンロードする前にフックを解除することが重要であることに注意してください。あなたは代わりにメイン閉鎖のデストラクタ関数への参照を返すことによってそれを行うことができます

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; 
})(); 

アンフックは次のようになります。通訳はガベージコレクタを持っているJavaScriptの

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

。言い換えれば、あなたが何かを参照しなければ、それはそれらを守っていないでしょう。

JSONをコールバック関数(JSONP)で使用するのが良い理由の1つです。

たとえば、各JSのためのあなたはHTTPレスポンスがある場合:

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

そして(コールバックの場合)は、引数として渡されたJSONオブジェクトへの参照を作成しません、それが機能した後、収集ごみになります完了する。

実際に参照を作成する必要がある場合は、何らかの理由でデータが必要になる場合があります。そうでない場合は、まず参照する必要があります。

名前空間オブジェクトに言及されたメソッドは、参照カウントが0になるまで保持される参照を作成するだけです。つまり、すべての参照を追跡して後で削除する必要があります。 DOMの参照が周囲にあります。 1つの参照だけがオブジェクトをメモリに保持しますが、単純な操作ではそれを実現せずに参照を作成することがあります。

0

素敵な議論。多くのことをクリアします。私はもう一つの心配があります。

window.MyModule.bar()をイベントにバインドすると、window.MyModuleが削除された後にイベントが誤ってトリガされた場合はどうなりますか?私にとって、動的にロードされたモジュールに名前空間を区切り、jsを分離することの全ポイントは、誤ってモジュール間でイベントハンドラをトリガすることを避けることです。 。(window.MyModule.bar)を

$(」。いくつかのクラス)をクリックします;:私がしなければ

例えば、(私のjQueryのを言い訳)

window.MyModuleを削除し、別のモジュールを読み込んで、誤ってsome-classというクラスがある要素をクリックするとどうなりますか?

関連する問題