Hacker News new | ask | show | jobs
by richardofyork 4733 days ago
nknighthb, I am just wondering. Did you downvote me because you think one part of my explanation was not specific enough?

First, you are correct that I specifically mentioned the logIf function when I discuss the specific example.But that does not take away from my thorough explanation of the main reason for the problem. In fact, everything I said about the logIt function applies to the doSomethingWithStr function, since they are both closures, so my explanation stands as is.

If you read my explanation again, you will see that I clearly explained that closures still have access to the outer function's scope, so both the logIt and the doSomethingWithStr functions have access to the outer function's scope chain even after the outer function or any of the other closures returns.

It is not until both all closures are destroyed or returns that the outer function's scope activation object is destroyed.

1 comments

If your explanation were all there was to it, then 'str' would not be destroyed when logIt alone were present. But it is.

logIt alone -> str is garbage collected

logIt + doSomethingWithStr -> str is not garbage collected

Your explanation could explain the latter behavior, but it does not explain the former.

Edit: To put it another way, you are addressing only one of the scenarios presented in the article, and you are assuming that scenario results in a behavior the article specifically says does not occur in empirical testing. This is a key point in the article, and your "explanations" are ignoring it.

Are you saying my explanation does not explain the following? "logIt alone -> str is garbage collected"

I don't see why you don't understand why I am saying. My first post explains in detail how closures work and why the issue is not a JS bug, though it is indeed a memory leak. All I can say is that I have explained the overall inner workings of closures in JS, and my explanation covers all the scenarios outlined in the blog post.

This is the crux of the matter of the entire blog post:

"...str is only referenced in the main body of run, and in doSomethingWithStr. doSomethingWithStr itself gets cleaned up once run ends… the only thing from run that escapes is the second closure, logIt. And logIt doesn’t refer to str at all! So even though there’s no way for any code to ever refer to str again, it never gets garbage collected!"

And I explained why that problem is observed and why closures work the way they do.

PS. I will humbly agree to disagree: I think that I have explained all the scenarios outlined in the blog post and you disagree with me. This is not a problem; there is nothing wrong with disagreeing.

Try answering this question specifically: Why is str garbage collected when logIt still exists?
Good question: I take it you are referring to the code below. The reason str is garbage collected is because of the modern implementation of the JS compiler in Chrome. Such modern JS compilers look specifically for such unused variables in closures, even when the variable is in the execution context of the closure.

To clarify, it is Chrome's decision to garbage collect the str variable in that context that resulted in str being garbage collected. It is not a result of a JavaScript bug.

Moreover, different browsers have different implementations for how they garbage collect variables in closures' scope chain. Heck, browsers do their own thing when it comes to many aspects of JavaScript.

On second thought (from our previous back and forth), you are correct that I did not explicitly discuss this specific issue in my earlier post. So you win :) and I have up-voted your two comments accordingly.

Here is the code I think you are referring to: var run = function () { var str = new Array(1000000).join('*'); var logIt = function () { console.log('interval'); }; setInterval(logIt, 100); }; setInterval(run, 1000);

Yeah, that's exactly what I mean.

The confusing part of your posts has been that you seem to have been portraying the retention of 'str' as a necessary behavior. Nobody disagrees that it's a permitted implementation, only that it's the one correct or best implementation, and it's made worse by the inconsistency between the two cases, which itself invites confusion.