JavaScriptのクロヌゞャヌ[パヌト2]

前の郚分 。







短絡



自動ガベヌゞコレクション



ECMAScriptは自動ガベヌゞコレクションを䜿甚したす。 仕様では詳现が定矩されおいないため、開発者はこれに察凊する必芁があり、䞀郚の実装ではガベヌゞコレクション操䜜をほずんど重芁芖しおいないこずが知られおいたす。 しかし、䞀般的な考えは、オブゞェクトを参照するこずが䞍可胜になった堎合実行可胜コヌドで䜿甚可胜な参照が残っおいないため、ガベヌゞコレクタヌおよび䜕らかの時点で削陀されるリ゜ヌスで䜿甚できるようになるずいうこずです。䜿甚され、解攟され、再利甚のためにシステムに戻されたす。



原則ずしお、これは実行コンテキストを離れた盎埌に発生したす。 スコヌプ構造、アクティベヌション/倉数オブゞェクト、および関数オブゞェクトを含む実行コンテキストで䜜成されたオブゞェクトはアクセスできなくなり、ガベヌゞコレクタヌが利甚できるようになりたす。



クロヌゞャヌを䜜成する



この関数呌び出しから関数呌び出しの実行のコンテキストで䜜成された関数オブゞェクトが返され、ネストされた関数ぞのリンクが別のオブゞェクトのプロパティに割り圓おられるず、クロヌゞャヌが圢成されたす。 たたは、そのような関数オブゞェクト、たずえばグロヌバル倉数、グロヌバルにアクセス可胜なオブゞェクトのプロパティ、たたは倖郚関数呌び出しぞの匕数ずしお参照によっお枡されるオブゞェクトぞの参照を盎接割り圓おるこずによっお。

function exampleClosureForm(arg1, arg2){ var localVar = 8; function exampleReturned(innerArg){ return ((arg1 + arg2)/(innerArg + localVar)); } /*     ,   exampleReturned */ return exampleReturned; } var globalVar = exampleClosureForm(2, 4);
      
      





これで、 exampleClosureFormの呌び出しを実行するコンテキストで䜜成された関数オブゞェクトは、グロヌバル倉数によっお参照され、ただ利甚可胜であるため、ガベヌゞコレクションによっお凊理できたせん。このオブゞェクトはglobalVarnが呌び出されたずきにも実行できたす。



しかし、グロヌバル倉数globalVarは関数オブゞェクトを参照するため、このオブゞェクトは[[scope]]プロパティで䜜成され、䜜成された実行コンテキストに属するアクティベヌション/倉数オブゞェクトを含むスコヌプチェヌンを参照するため、グロヌバルオブゞェクトを含む。 アクティベヌション/倉数オブゞェクトはガベヌゞコレクタヌで凊理できず、 globalVarで参照される関数オブゞェクトが実行されるず、 [[scope]]プロパティで参照されるスコヌプチェヌン党䜓が毎回䜜成される実行コンテキストのスコヌプに远加されたす関数オブゞェクトを呌び出したす。



クロヌゞャヌが䜜成されたす。 ネストされた関数のオブゞェクトには自由倉数があり、この関数の可芖性のチェヌンにあるアクティベヌションオブゞェクト/倉数は、それらを接続する媒䜓です。



アクティベヌションオブゞェクト/倉数がトラップされるのは、 それぞの参照は、 globalVar倉数によっお参照される関数オブゞェクトの内郚[[scope]]プロパティに割り圓おられたスコヌプチェヌンに含たれたす。 アクティベヌションオブゞェクト/倉数は、その状態ずずもに保存されたす。 プロパティの倀を䜿甚したす。 内郚関数の呌び出しの実行実行コンテキストのスコヌプを解決するプロセスでは、このアクティベヌションオブゞェクト/倉数の名前付きプロパティに察応する識別子が、単にこのオブゞェクトのプロパティずしお蚈算されたす。 これらのプロパティの倀は、䜜成された実行コンテキストを終了した埌でも読み取りおよび蚭定できたす。



䞊蚘の䟋では、このアクティベヌション/倉数オブゞェクトは、倖郚関数が完了した実行コンテキストが終了した時点での仮パラメヌタヌの倀、内郚関数ずロヌカル倉数の定矩を衚す状態を持ちたす。 arg1プロパティの倀は2 、 arg2の倀は4 、 localVarの倀は8、 exampleReturnedプロパティは、倖郚関数から返されるネストされた関数のオブゞェクトぞの参照です。 以䞋では、䟿宜䞊、このアクティベヌションオブゞェクト\倉数をActOuter1ずしお瀺したす。



もう䞀床exampleClosureFormを呌び出すず

 var secondGlobalVar = exampleClosureForm(12, 3);
      
      





-新しいアクティブ化オブゞェクトを䜿甚しお、新しい実行コンテキストが䜜成されたす。 そしお、匕数倀arg1-12およびarg2-3を持぀2番目の実行コンテキストからのアクティベヌションオブゞェクトを含むスコヌプチェヌンを参照する、独自の個別のプロパティ[[scope]]で新しい関数オブゞェクトが返されたす。 以䞋では、䟿宜䞊、このアクティベヌションオブゞェクト\倉数をActOuter2ずしお瀺したす。



exampleClosureFormぞの2回目の呌び出しによっお、2番目の異なるクロヌゞャヌが䜜成されたした。



それぞれglobalVarずsecondGlobalVarで参照されるexampleClosureFormを実行しお䜜成されたこれらの関数オブゞェクトは䞡方ずも、匏arg1 + arg2/innerArg + localVarを返したす。 4぀の識別子に察しお耇数のステヌトメントを実行したす。 これらの識別子の蚈算方法によっお、クロヌゞャの目的ず意味が決たりたす。



globalVar  globalVar2によっお参照される関数オブゞェクトの実行を怜蚎しおください。 新しい実行コンテキストが䜜成され、アクティベヌションオブゞェクトActInner1ず呌びたしょうが、実行された関数オブゞェクトの[[scope]]プロパティが参照するスコヌプチェヌンの先頭に远加されたす。 ActInner1は、仮パラメヌタヌに匕数2の倀が割り圓おられた埌にinnerArgプロパティを取埗したす。 新しい実行コンテキストのスコヌプチェヌンは、ActInner1-> ActOuter1->グロヌバルオブゞェクトになりたす。



識別子名は、この方法でスコヌプチェヌンを通じお解決されたす。 匏arg1 + arg2/innerArg + localVarの倀を返すために、これらの識別子の倀は、スコヌプチェヌンから各オブゞェクトの識別子に察応する名前を持぀プロパティを順番に怜玢するこずで決定されたす。



チェヌンの最初のオブゞェクトはActInner1で、倀が2の innerArgプロパティがありたす。 残りの3぀の識別子は、ActOuter1の名前付きプロパティに察応しおいたす。 倀が2の arg1 、 arg2は4 、 localVarは8です。 関数呌び出しは2 + 4/2 + 8を返したす。



これを、 secondGlobalVarで参照される別の同䞀の関数オブゞェクトの実行ず比范しおください secondGlobalVar5 。 新しい実行コンテキストActInner2のアクティベヌションオブゞェクトに名前を付けたす。チェヌンは、ActInner2-> ActOuter2->グロヌバルオブゞェクトのようになりたす。 ActInner2はinnerArgを5ずしお返し、ActOuter2はarg1 、 arg2およびlocalVarをそれぞれ12、3および8ずしお返したす。 戻り倀 12 + 3/5 + 8 。



secondGlobalVarを再床実行するず、スコヌプチェヌンの先頭に新しいアクティベヌションオブゞェクトが衚瀺されたすが、ActOuter2はチェヌン内の次のオブゞェクトのたたであり、その名前付きプロパティの倀は識別子arg1 、 arg2およびlocalVarの解決に再び䜿甚されたす。



このようにしお、ECMAScriptのネストされた関数は、仮パラメヌタヌ、ネストされた関数の宣蚀、および䜜成された実行コンテキストのロヌカル倉数ぞのアクセスを受け取り、保持したす。 したがっお、クロヌゞャを䜜成するず、そのような関数オブゞェクトはこれらの倀を参照し続け、存圚しおいる間にそれらを読み取っお倉曎するこずができたす。 ネストされた関数が䜜成された実行コンテキストのアクティベヌションオブゞェクト/倉数は、ネストされた関数ぞのすべおの参照が解攟され、関数オブゞェクトが参照されるたで、関数オブゞェクトの[[scope]]プロパティが参照するスコヌプのチェヌンに残りたすガベヌゞコレクタヌで䜿甚できなくなりたす今埌、スコヌプチェヌン内のすべおのオブゞェクトず䞀緒に䞍芁になりたす。



入れ子関数自䜓に入れ子関数を含めるこずができたす。 クロヌゞャヌを圢成するために関数によっお返されるネストされた関数は、ネストされた関数を返し、クロヌゞャヌを䜜成できたす。 添付ファむルごずに、スコヌプチェヌンは、ネストされた関数オブゞェクトが䜜成された実行コンテキストず共に発生する远加のアクティベヌションオブゞェクトを受け取りたす。 ECMAScript仕様では、 スコヌプチェヌンが有限であるこずが必芁ですが、その長さに制限はありたせん。 おそらく、実際のいく぀かの実装にはいく぀かの制限がありたすが、これたでのずころ特定の数量の報告はありたせんでした。 どうやら、機胜のさらなる投資の可胜性は、誰もが必芁ずするよりも倚いです。



クロヌゞャヌで䜕ができたすか



奇劙に思えるかもしれたせんが、この質問に察する答えは絶察にすべおです。 私は、クロヌゞャヌによっおECMAScriptが䜕でも゚ミュレヌトできるようになるずいう事実に぀いお話しおいたす。制限は、この゚ミュレヌションを考案しお実装する胜力にのみありたす。 これは少しわかりにくいので、もっず実甚的なものから始める方が良いかもしれたせん。



䟋1関数参照を䜿甚したsetTimeout



クロヌゞャヌは、実行前に実行する関数のパラメヌタヌを提䟛するためによく䜿甚されたす。 たずえば、関数をsetTimeout関数の最初の匕数ずしお枡す必芁がある堎合、これはWebブラりザヌ環境で䞀般的です。



setTimeoutは、ミリ秒単䜍で衚された間隔2番目の匕数からの埌、最初の匕数からアクセス可胜な関数たたはコヌドのjavascript行ですが、この堎合はそうではありたせんの実行時間を蚭定したす。 setTimeoutを䜿甚するには、この関数を呌び出しお、関数オブゞェクトぞの参照を最初の匕数ずしお、ミリ秒単䜍の間隔を2番目ずしお枡す必芁がありたすが、関数オブゞェクトぞの参照には、この関数のスケゞュヌルされた実行のパラメヌタヌを含めるこずはできたせん。



ただし、ネストされた関数のオブゞェクトぞの参照を返す別の関数を呌び出すこずができたす。この関数は、 setTimeout関数ぞの参照によっお枡されたす。 ネストされた関数で䜿甚されるパラメヌタヌは、それを返す関数が呌び出されたずきに送信されたす。 setTimoutは匕数を枡さずにネストされた関数を実行したすが、このネストされた関数は、それを返した倖郚関数を呌び出すこずで提䟛されるパラメヌタヌに匕き続きアクセスできたす。

 function callLater(paramA, paramB, paramC){ /*      ,   : */ return (function(){ /*        setTimeout,     ,      ,     */ paramA[paramB] = paramC; }); } ... /*  ,       ,     .  ,        ,    .         : */ var functRef = callLater(elStyle, "display", "none"); /*   setTimeout,     ,   funcRef,   : */ hideMenu=setTimeout(functRef, 500);
      
      





䟋2関数をオブゞェクトむンスタンスメ゜ッドに関連付ける



関数オブゞェクトぞの参照が割り圓おられ、関数が将来のある時間埌に実行される堎合、他の倚くの状況がありたす。この堎合、この関数の実行のためのパラメヌタヌを準備するず䟿利です。実行時に簡単にアクセスできたせんが、割り圓おの瞬間たで䞍明です。



1぀の䟋は、特定のDOM芁玠ずの盞互䜜甚をカプセル化するように蚭蚈されたjavascriptオブゞェクトです。 このDOM芁玠の察応するむベントがトリガヌされたずきに実行するdoOnClick 、 doMouseOver 、およびdoMouseOutメ゜ッドが含たれおいたすが、さたざたなDOM芁玠に関連付けるために䜜成されたjavascriptオブゞェクトのむンスタンスはいく぀でもあり、個々のオブゞェクトむンスタンスはそれらの方法を知らない堎合がありたすそれらが䜜成されるコヌドに適甚されたす。 これらのオブゞェクトむンスタンスは、グロヌバルに参照される方法を決定できたせん。 どのグロヌバル倉数存圚する堎合にそれらぞの参照が割り圓おられるかはわかりたせん。



したがっお、問題は、むベントを凊理する関数の実行にありたす。関数は、javascriptオブゞェクトの特定のむンスタンスに関連付けられ、このオブゞェクトのどのメ゜ッドを呌び出す必芁があるかを認識しおいたす。



次の䟋では、オブゞェクトむンスタンスを芁玠のむベントハンドラヌに関連付けるクロヌゞャに基づく単玔な汎化関数を䜿甚したす。 むベントハンドラヌを実行するず、むベントオブゞェクトず関連付けられた芁玠ぞの参照が枡されるオブゞェクトむンスタンスの特定のメ゜ッドが呌び出され、このメ゜ッドによっお返される倀が返されるずしたす。

 /*  ,       .       .      obj,   ,      ,   methodName -   . */ function associateObjWithEvent(obj, methodName){ /*   , , ,      DOM : */ return (function(e){ /*  ,     e  ,      DOM,    ,   IE,         ,   */ e = e||window.event; /*      obj,      methodName   ,          ,    ,     this ( , ..        ,      ) */ return obj[methodName](e, this); }); } /*  -  ,   DOM ,  ID      .      , ,      onclick, onmouseover  onmouseout,       . */ function DhtmlObject(elementId){ /*  ,     DOM  ( null,    )   ID  ,   .      el. */ var el = getElementWithId(elementId); /*  el      boolean     if ,   el   ,    ,    null - .  ,    ,    el    DOM. */ if(el){ /*       ,     associateObjWithEvent,   (    this)  ,     ,     .  associateObjWithEvent     ,      DOM .         javascript    . */ el.onclick = associateObjWithEvent(this, "doOnClick"); el.onmouseover = associateObjWithEvent(this, "doMouseOver"); el.onmouseout = associateObjWithEvent(this, "doMouseOut"); ... } } DhtmlObject.prototype.doOnClick = function(event, element){ ... //   doOnClick. } DhtmlObject.prototype.doMouseOver = function(event, element){ ... //   doMouseOver. } DhtmlObject.prototype.doMouseOut = function(event, element){ ... //   doMouseOut. }
      
      





したがっお、グロヌバルな名前空間に圱響を䞎えたり 、 DhtmlObjectの他のむンスタンスず衝突したりするこずなく、 DhtmlObjectのむンスタンスをDOM芁玠に関連付けるこずができ、他のコヌドによる䜿甚方法を考慮する必芁はありたせん。



䟋3盞互接続された機胜のカプセル化



クロヌゞャヌを䜿甚しお、盞互接続され盞互䟝存するコヌドをグルヌプ化する远加のスコヌプを䜜成しお、偶発的な盞互䜜甚のリスクを最小限に抑えるこずができたす。 文字列を䜜成する関数があり、連結操䜜の繰り返しおよび倚くの䞭間文字列の䜜成を避けるために、配列を䜿甚しお文字列の䞀郚を特定の順序で保存し、 Array.prototype.joinを䜿甚しお結果を出力するこずをお勧めしたす匕数ずしお空の文字列を䜿甚したす。 配列は出力のバッファヌずしお䜿甚されたすが、関数内でロヌカルに定矩されおいる堎合、関数が実行されるたびに再䜜成されたす。これは、関数の呌び出しごずに配列の倉数の内容のみが倉曎される堎合は䞍芁です。



1぀の方法は、この配列のグロヌバル倉数を䜜成しお、毎回䜿甚するたびに再䜜成する必芁がないようにするこずです。 ただし、その埌、バッファ配列を䜿甚する関数を参照するグロヌバル倉数に加えお、配列自䜓を参照する別のグロヌバルプロパティがありたす。 その結果、コヌドを制埡するこずがより困難になりたす;他の堎所で䜿甚する堎合、䜜成者は関数定矩ず配列定矩の䞡方を远加する必芁があるこずを芚えおおく必芁がありたす。 たた、このようなコヌドは、関数名の䞀意性を確認するこずに加えお、この関数が䟝存する配列の名前がグロヌバル名前空間にも䞀意であるこずも確認する必芁があるため、他のコヌドず組み合わせるこずが困難です。



クロヌズするず、バッファヌ配列をそれに䟝存する関数に関連付けるこずができたすそしおきちんずパッケヌゞ化できたす。同時に、名前空間の競合やランダムな盞互䜜甚のリスクなしに、グロヌバル名前空間の倖郚に配列に蚭定されたプロパティ名を保存できたす。



トリックは、゚クスプレッション関数に組み蟌みむンラむン実行するこずにより、1぀の远加の実行コンテキストを䜜成するこずです。これにより、倖郚コヌドで䜿甚されるネストされた関数が返されたす。 バッファヌ配列は、組み蟌みむンラむン実行を䌎う匏関数のロヌカル倉数ずしお定矩されたす。 実行は1回行われるため、配列は1回だけ䜜成されたすが、それに䟝存する関数は繰り返し䜿甚できたす。



次のコヌドでは、ほずんど倉曎されないHTML文字列を返す関数が䜜成されたすが、この文字シヌケンスには、関数が呌び出されたずきにパラメヌタヌを介しおアクセス可胜な倉数情報が含たれおいる必芁がありたす。



ネストされた関数オブゞェクトぞの参照は、匏関数に組み蟌たれた実行から返され、グロヌバル倉数に割り圓おられたす。したがっお、この関数オブゞェクトはグロヌバル関数ずしお呌び出すこずができたす。 バッファ配列は、倖郚匏関数のロヌカル倉数ずしお定矩されたす。 グロヌバル名前空間に配眮されおおらず、それを䜿甚する関数の呌び出しごずに再䜜成されたせん。

 /*   getImgInPositionedDivHtml       -,      -.      HTML,     DIV,   IMG,           . */ var getImgInPositionedDivHtml = (function(){ /* bufferAr - ,     - .            , ..         .     -  ,       . */ var buffAr = [ '<div id="', '', // 1, DIV ID  '" style="position:absolute;top:', '', // 3, DIV top  'px;left:', '', // 5, DIV left  'px;width:', '', // 7, DIV width 'px;height:', '', // 9, DIV height 'px;overflow:hidden;\"><img src= '', // 11, IMG URL '\" width= '', // 13, IMG width '\" height= '', // 15, IMG height '\" alt= '', // 17, IMG alt  '\"><\/div>' ]; /*    ,     -.           getImgInPositionedDivHtml(...) */ return (function(url, id, width, height, top, left, altText){ /*           */ buffAr[1] = id; buffAr[3] = top; buffAr[5] = left; buffAr[13] = (buffAr[7] = width); buffAr[15] = (buffAr[9] = height); buffAr[11] = url; buffAr[17] = altText; /*  ,            (   ,       ) */ return buffAr.join(''); }); //  -. })(); /*^^-  (inline)   - */
      
      





1぀の関数が別のたたは耇数の関数に䟝存しおいるが、これらの他の関数が他のコヌドで盎接呌び出されるこずを意図しおいない堎合、同じ手法を䜿甚しおこれらの関数をオヌプンアクセスの1぀にグルヌプ化できたす。したがっお、耇雑な倚機胜プロセスが、簡単に移怍できるカプセル化されたコヌドモゞュヌルで䜜成されたす。



その他の䟋





おそらく、クロヌゞャヌの最も有名なアプリケヌションの1぀は、Douglas Crockford ECMAScriptオブゞェクトでプラむベヌトむンスタンス倉数を゚ミュレヌトする手法です。ECMAScriptオブゞェクトのプラむベヌト静的メンバヌの゚ミュレヌションを含む、組み蟌みのアクセシビリティず可芖性を含むあらゆる皮類のスコヌプ構造で拡匵できたす。



クロヌゞャヌアプリケヌションは無数にありたすが、それらがどのように機胜するかを理解するこずが、おそらくそれらをどのように䜿甚できるかを理解するための最良のガむドです。



ランダム閉包



埋め蟌たれた関数を、それが䜜成された関数の本䜓の倖郚でアクセス可胜にするず、クロヌゞャヌが圢成されたす。したがっお、クロヌゞャヌは非垞に簡単に䜜成できたす。その結果、クロヌゞャヌが蚀語の機胜であるこずを理解しおいないjavascript開発者は、クロヌゞャヌが䜜成されたこずや結果になる可胜性があるこずを認識せずに、明らかな結果なしでさたざたなタスクに埋め蟌み関数を䜿甚したす。



偶発的なクロヌゞャの䜜成には、次のセクションで説明するIEのメモリリヌク問題などの副䜜甚がありたす。たた、コヌドのパフォヌマンスに圱響を䞎える可胜性がありたす。理由は、クロヌゞャヌ自䜓ではなく、実際、慎重に䜿甚するず、クロヌゞャヌは効果的なコヌドの䜜成に倧きく貢献する可胜性がありたす。ポむントはネストされた関数にあり、その䜿甚は効率に圱響する可胜性がありたす。



ネストされた関数がDOM芁玠のむベントハンドラヌずしお䜿甚される堎合、䞀般的な方法です。たずえば、次のコヌドを䜿甚しお、onclickむベントハンドラヌをリンク芁玠に远加できたす。

 /*   ,        href            */ var quantaty = 5; /*         (     linkRef),       onclick,      quantaty   href        ,    true,  ,    ,    href,     . */ function addGlobalQueryOnClick(linkRef){ /*   linkRef     true ( ,     ) */ if(linkRef){ /*  -            onclick   */ linkRef.onclick = function(){ /*   -      href ,         */ this.href += ('?quantaty='+escape(quantaty)); return true; }; } }
      
      





addGlobalQueryOnClick関数が呌び出されるたびに、新しいネストされた関数が䜜成されたす割り圓おられたずきにクロヌゞャヌが圢成されたす。効率の芳点から、addGlobalQueryOnClickが1回たたは2回だけ呌び出されたかどうかは関係ありたせんが、関数が集䞭的に䜿甚された堎合、倚くの個別の関数オブゞェクトが䜜成されたした内郚匏関数の蚈算ごずに1぀。



䞊蚘のコヌドは、内郚関数が䜜成された関数の倖で利甚可胜になったずいう事実぀たり、クロヌゞャヌの結果を利甚しおいたせん。むベントハンドラヌずしお個別に䜿甚する関数を定矩し、この関数ぞのリンクをむベントハンドラヌのプロパティに割り圓おるこずで、たったく同じ効果を実珟できたす。単䞀の関数オブゞェクトが䜜成され、このむベントハンドラヌを䜿甚するすべおの芁玠は、この単䞀の関数ぞのリンクを䜿甚したす。

 /*   ,        href            */ var quantaty = 5; /*         (     linkRef),       onclick,      quantaty   href        ,    true,  ,    ,    href,     . */ function addGlobalQueryOnClick(linkRef){ /*   linkRef     true ( ,     ) */ if(linkRef){ /*          ,  ,     . */ linkRef.onclick = forAddQueryOnClick; } } /*   ,         ,         href  . */ function forAddQueryOnClick(){ this.href += ('?quantaty='+escape(quantaty)); return true; }
      
      





最初のバヌゞョンのネストされた関数は、その䜿甚によっお䜜成されたクロヌゞャヌを䜿甚するこずを意図しおいないため、ネストされた関数を䜿甚せず、したがっお本質的に同䞀の関数オブゞェクトのセットを䜜成するプロセスを繰り返さないほうが効率的です。



同様の原則がコンストラクタヌ関数オブゞェクトに適甚されたす。次のコンストラクタヌ構造に䌌たコヌドが衚瀺されるこずは珍しくありたせん。

 function ExampleConst(param){ /*      -             */ this.method1 = function(){ ... //   }; this.method2 = function(){ ... //   }; this.method3 = function(){ ... //   }; /*     . */ this.publicProp = param; }
      
      





コンストラクタヌを䜿甚しお、新しいExampleConstnを実行しおオブゞェクトを䜜成するたびに、メ゜ッドずしお機胜する関数オブゞェクトの新しいセットが䜜成されたす。぀たり、より倚くのオブゞェクトむンスタンスが䜜成されるず、より倚くの察応する関数オブゞェクトが䜜成されたす。



ダグラスクロックフォヌドのjavascriptオブゞェクトのプラむベヌトフィヌルドを゚ミュレヌトする手法では、コンストラクタヌ内で䜜成されたオブゞェクトのオヌプンプロパティにネストされた関数のオブゞェクトぞの参照を割り圓おる結果ずしお生じるクロヌゞャヌが䜿甚されたす。ただし、オブゞェクトのメ゜ッドがコンストラクタヌ内で圢成されるクロヌゞャヌを利甚しない堎合、各むンスタンスに远加の関数オブゞェクトを䜜成するず、オブゞェクトの䜜成プロセスが遅くなり、より倚くのリ゜ヌスが必芁になりたす。



この堎合、関数オブゞェクトを䞀床䜜成し、コンストラクタヌのプロトタむプオブゞェクトの察応するプロパティにそれらぞの参照を割り圓おるず、このコンストラクタヌによっお䜜成されたすべおのオブゞェクトで䜿甚できたす。

 function ExampleConst(param){ /*      */ this.publicProp = param; } /*       -            prototype  */ ExampleConst.prototype.method1 = function(){ ... //   }; ExampleConst.prototype.method2 = function(){ ... //   }; ExampleConst.prototype.method3 = function(){ ... //   };
      
      







Internet Explorerのメモリリヌクの問題



Internet Explorerブラりザバヌゞョン4〜6テスト時は珟圚のバヌゞョンは6でテスト枈みには、ガベヌゞコレクションシステムに欠陥がありたす。これらの環境オブゞェクトが「円圢」リンクの䞀郚である堎合、ECMAScriptオブゞェクトず䞀郚の環境オブゞェクトの凊理が劚げられたす。この堎合の環境オブゞェクトは、DOM Nodeオブゞェクトドキュメントオブゞェクトずその子孫を含むおよびActiveXオブゞェクトずしお理解されたす。埪環リンクにそれらの1぀以䞊が含たれおいる堎合、参加しおいるオブゞェクトはどれも解攟されず、それらが䜿甚するメモリはブラりザが閉じられるたでシステムにアクセスできなくなりたす。



埪環参照ずは、2぀以䞊のオブゞェクトが開始点に぀ながるように盞互に参照する堎合です。たずえば、オブゞェクト1にオブゞェクト2を参照するプロパティがあり、オブゞェクト2にオブゞェクト3を参照するプロパティがあり、オブゞェクト3にオブゞェクト1を参照するプロパティがある堎合、玔粋なECMAScriptオブゞェクトの堎合、オブゞェクト1 2たたは3、他のオブゞェクトは参照を停止し、盞互に参照するだけであるずいう事実が認識され、ガベヌゞコレクタヌで䜿甚できるようになりたす。ただし、Internet Explorerの堎合、これらのオブゞェクトの少なくずも1぀がDOM NodeたたはActiveXオブゞェクトである堎合、ガベヌゞハンドラヌは、この埪環関係がシステムの他の郚分から分離されおいるこずを確認できず、それらを解攟したす。代わりに、ブラりザが閉じられるたで、それらはすべおメモリに残りたす。



クロヌゞャヌは、埪環参照の䜜成に非垞に適しおいたす。たずえば、クロヌゞャヌを䜜成する関数のオブゞェクトがDOM Nodeオブゞェクトのむベントハンドラヌずしお割り圓おられ、このノヌドぞのリンクがこの関数のスコヌプ内のアクティベヌションオブゞェクト/倉数のプロパティの1぀に割り圓おられおいる堎合、埪環リンクが衚瀺されたす。 DOM_Node.onevent-> function_object。[[Scope]]-> scope_chain-> Activation_object.nodeRef-> DOM_Node。これは非垞に簡単であり、すべおのペヌゞに共通のコヌドの䞀郚でこのようなリンクを圢成するサむトを少し芋るず、ほずんどのシステムメモリ堎合によっおはすべおを䜿甚できたす。



IEでonunloadむベントを䜿甚しおむベントを凊理する機胜ぞのリンクをリセットするなど、埪環リンクの䜜成を避け、回避できない堎合は修正措​​眮を講じる必芁がありたす。問題を特定し、クロヌゞャおよびそのメカニズムを理解するこずで、IEでこの問題を回避できたす。



リチャヌド・コヌンフォヌドによっお曞かれたした。2004幎3月。

修正および提案者

Martin Honnen。

ダン・゚ルワン・ペリオうん。

ラッセ・ラむヒシュタむン・ニヌルセン。短絡怜出

マむクシロッコ。

ゞョン・ストックトン博士。

ギャレット・スミス。



Lyudmila Likhovidの翻蚳にご参加いただきありがずうございたす。



All Articles