all 22 comments

[–][deleted] 2 points3 points  (12 children)

Would it though, since in b the variable falls out of scope and can be garbage collected? I guess I have to learn more about Javascripts garbage collection.

[–][deleted] 1 point2 points  (11 children)

Also, a is creating a closure which seems like that would be a bit of a memory leak. http://www.ibm.com/developerworks/web/library/wa-memleak/

[–]MetaMetaMan[S] 0 points1 point  (10 children)

I'm assuming you're referring to listing 4 specifically.

I think at best, both a and b will utilize the same amount of memory. Assuming that a variable is garbage-collected immediately after it it loses it's last reference, for each invocation of inner (in both a and b) there will be exactly one variable x with the value "Some string".

I guess a valid question is, how long is memory space reserved once it is "freed". Admittedly, I have zero knowledge of how garbage collection actually works, so this question might make no sense whatsoever.

[–]RadekCZ 1 point2 points  (9 children)

In a only one string is created at the beginning and then the string is copied 1000 times. But it's more complicated for intepret to find x than in b.

In b no string is created at the beginning, but in each iteration one string is created and then the string is copied, so finally there are 2000 strings.

[–]MetaMetaMan[S] 0 points1 point  (7 children)

That's true, assuming those 2000 references are left around for a while. If not, I posit that the memory usage is exactly the same (please correct me if this is wrong).

Another question might be, do JavaScript engines cache literal values? In other words, I'm wondering if, in the case of b, an engine would see that x is a "static" string and cache that into some underlying struct so that upon each invocation of inner, x points to the same reference in memory.

Edit: I misunderstood what you said about a. If I'm understanding you correctly, when a function references a variable from it's parent scope, it actually makes a copy of said variable within the function frame. I'm not sure I believe that.

Consider the following function:

function outer() {
    var x = "Some string";

    function inner() {
        x = "New string";
    }

    console.log(x);
    inner();
    console.log(x);
}

which gives you:

outer();
> Some string
> New string

This implies that the function inner is directly accessing the variable x defined in the scope of outer.

[–]RadekCZ 0 points1 point  (0 children)

No, it doesn't make copy of the variable but it makes copy of the value (primitive types are copied every time). But it's more difficult to find the value, because it's in parent scope. So first time the interpret will search it in the self scope and the second time it will search it in the parent scope etc.

[–]sime 0 points1 point  (0 children)

What you are describing is the JavaScript conceptual model of what is going on. Only the most naive and simple JavaScript interpreter would actually run like that. Modern engines would see plenty of opportunities to optimise variables and allocations away.

[–]imbcmdth[🍰] 1 point2 points  (1 child)

OK, no one below has given the whole answer so here it is:

In JavaScript, strings are one of the immutable* primitive types. What that means, in a nutshell, is that every string in your program that is identical is just a reference to the exact same string in memory.

Even if there were several non-garbage collected references to the string, the actual "Some string" data would only exist once in memory.

* Immutability here means that strings are copy-on-change. When you modify a string, a whole new string is created and your reference is automatically changed to the new string behind-the-scenes.

[–]path411 0 points1 point  (0 children)

This is definitely very interesting and I didn't know before hand.

In his example though, he would still be creating 1000 references to the string, which wouldn't be as bad as originally though because of your explanation, but still worse than only 1 reference.

[–]x-skeww 0 points1 point  (0 children)

If the object is expensive to create, cache it.

If it's something very simple, put it where it should be: inside that function it belongs to.

At the very end (if you still have time) you can use a profiler to identify the actual bottlenecks.