閉包問題を記入する


テーマ
今日は経典の閉塞メモリが漏れています.ちょっと分かりにくいです.ここでもう一度閉塞の論理を整理します.
        var t = null;
        var replaceThing = function() {
            var o = t
            var unused = function() {
                if (o)
                    console.log("hi")
            }
            t = {
                    longStr: new Array(1000000).join('*'),
                    someMethod: function() {
                      console.log(1)
                    }
                }
        }
        setInterval(replaceThing, 1000)
クローズド分析
クローズドはみんな知っています.ポイントは二つの面から理解します.
  • 関数ネスティング関数は、外層関数が作用する領域の変数を内層関数が参照し、大域的環境の変数によって内部関数が参照されることで、クローズドが形成される.
  • 関数内部で定義されたすべての関数は、同一のクローズドオブジェクトを共有する.
  • したがって、一つの関数が先に関数ネスティング関係を決定してから、内部関数が外層関数のスコープ内の変数を参照しているかどうかを見てください.このテーマでは、内層関数unusedは外層関数replaceThingのスコープ内の変数oを参照しています.ここでは、閉じられたオブジェクトがあります.関数tは、大域変数によって参照されていないので、この閉じられたオブジェクトは、関数が実行された後に破棄される.
    しかし、後のコードを見て、unused関数は大域変数someMethodに大きなオブジェクトを構成しています.ここでは「内層関数は大域環境下の変数によって参照されます」という定義に合致しています.「関数内部で定義されたすべての関数が同じクローズドオブジェクトを共有する」ため、t関数はsomeMethodと同じクローズドオブジェクトを共有し、変数unusedの参照を暗黙的に保持し、oの循環参照を形成し、メモリ漏れをもたらしている.
    解決方法
    この循環参照を切断するということは、t -> someMethod -> o -> t -> ...から前回のoまでの参照を切断するということであり、関数知性の最後にtを加えるとよい.
    問題の参考
    テーマ ギthub討論