javascript - How do double closures break circular references? - Stack Overflow

I was reading about how circular references cause memory leaks in IE, but I was pretty confused on an e

I was reading about how circular references cause memory leaks in IE, but I was pretty confused on an example using a closure within closure to break the circular reference:

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    };
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

My head got all wrangled with what referenced to what, which are the closures, which are the scope objects. Can someone break it down more explicitly than MDN? Thanks.

I was reading about how circular references cause memory leaks in IE, but I was pretty confused on an example using a closure within closure to break the circular reference:

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    };
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

My head got all wrangled with what referenced to what, which are the closures, which are the scope objects. Can someone break it down more explicitly than MDN? Thanks.

Share Improve this question asked Feb 21, 2014 at 20:31 Tri NoensieTri Noensie 8269 silver badges24 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 8

If you had

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
        // can access `el` here
    };
    var el = document.getElementById('el');
    el.onclick = clickHandler;
}

then el has a reference to clickHandler, but clickHandler also has a reference to el, because it's a closure. -> circular reference (in IE)

By introducing a new scope, you make el local, so it it is not accessible by clickHandler, -> no circular reference.

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
        // cannot access `el` here
    };
    (function() {
        // `el` is local to this immediately invoked function
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

So, the solution to the memory leak problem is not to introduce yet another closure, it is to create a new scope, that "shields" the values from each other (in one direction at least).

The rules of thumb that I go by:

For JavaScript closures to be created, there has to be nested functions and the inner function must have access to or is refered to by (let's just say "touch" for short) a variable in the outer function. If either of these 2 criteria is not found, then there's no closure in JavaScript.

Memory leaks occur when such variable (mentioned in the above paragraph) in the outer function happens to be a DOM element.

In the Mozilla article, let's visit the first example:

function addHandler() {
    var el = document.getElementById('el');
    el.onclick = function() {
        this.style.backgroundColor = 'red';
    };
}

Clearly, there is one function nested inside another function, and the inner function is assigned to a property of a variable (el) in the outer scope, so there is a closure created. This variable el also happens to be a DOM element, hence there's memory leak as explained in the article.

In the second example that you posted,

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    };
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

There's an outer function, and nested inside this outer function are 2 nested (inner) functions, but they are at the same level, meaning one is not nested inside the other. The second nested function also has access to a local variable (clickHandler) in the outer function, so there's a closure that gets created. However, there's no memory leaks because this local variable (clickHandler) in the outer function is not a DOM element. The local variable el does not contribute to memory leaks because it's local to the second nested function and not defined in the outer function addHandler(). In other words, it is local to the second nested function, it is not accessible to the first nested function, hence there's no chance for memory leaks.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745091455a4610718.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信