1

Let's assume that ajax response is 5mb which i get from an ajax call.

function(ajaxresponse){

    var ajaxdata = ajaxresponse;

    then

    var ajaxdata2 = ajaxresponse; //as per the reply below this is a reference and hence new memory isn't allocated

    var ajaxdata3 = JSON.parse(JSON.stringify(ajaxresponse));

}

Would 15mb, 10 mb or 5mb be utilized?

Esailija
  • 138,174
  • 23
  • 272
  • 326
Samosa
  • 845
  • 7
  • 19
  • 4
    5 MB - you are duplicating the reference - not the data – Sebastian Oct 02 '13 at 06:34
  • 1
    I believe you are just creating pointers to the original 'ajaxresponse' parameter. So there is no new memory allocation. You can test this by changing something in ajaxdata2 - it should also have changed in ajaxdata and ajaxresponse – mcbex Oct 02 '13 at 06:36
  • `ajaxdata2` is just a reference to the value in `ajaxdata` No new value is created. – Joe Simmons Oct 02 '13 at 06:39
  • Wow that is something i didn't know ! – Samosa Oct 02 '13 at 06:44
  • Yeah sorry...this was the my original intent of asking the question... added a comment so the the replies are still relevent. – Samosa Oct 02 '13 at 06:56
  • @ZendNoob ok I have edited it to ask about both duplicating reference and content – Esailija Oct 02 '13 at 06:57

1 Answers1

2

It's quite simple. JavaScript always passes/assigns by value, but an object's value is never really assigned to a variable. The way to think about objects and the memory management in JS is something like this:

All Objects (be it functions, object literals, arrays, prototypes...) reside somewhere in memory. These spaces in memory can either be referenced by a variable or not. But they stay put as it were. You can have any number of variables that are assigned the address of this object, but you can't copy the object itself, not directly anyway.
Check this answer which contains a number of diagrams and some more details on how JS works, including links to even more info...

Just try:

var a = {foo: 'bar'},
b;
b = a;
console.log(b.foo);//bar
b.foo += ' appended through b reference';
console.log(a.foo);//bar appended through b reference

a and b reference the same object, no additional memory required... save for the minute bit of mem required to store the b variable.
What the actual value is of a or b in this example is something like 0XB16B00B6. Or in C-speak, they actually behave as a dereferenced pointer.


In some cases, people do want to copy objects. Now this is quite hard to accomplish, owing to JS's design. If the object contains nothing but data, then the easiest way of doing this is:

var copiedObj = JSON.parse(JSON.stringify(someObject));

But if you're dealing with an object that also carries its own methods, then you're in a whole new world of trouble, and you'll have to do something like this:

//after doing:var copiedObj = JSON.parse(JSON.stringify(someObject));
function copyFunctions(srcObj, targetObj)
{
    var prop;
    for (prop in srcObj)
    {
        if (srcObj[prop] instanceof Object)
        {
            if (srcObj[prop] instanceof Function)
            {
                targetObj[prop] = srcObj[prop];//this is a REFERENCE, still
                //OR, to ensure correct this binding!
                targetObj[prop] = (function(rebind, actualFunc)
                {
                    return function()
                    {
                        actualFunc.bind(this);
                        var returnVal = actualFunc.apply(this, [].slice.call(arguments));
                        actualFunc.bind(rebind);
                    };
                }(srcObj, srcObj[prop]));
            }
            else
            {
                if (srcObj.hasOwnProperty(prop))
                {//avoid copying prototypal methods
                    targetObj[prop] = copyFunctions(srcObj[prop], targetObj[prop] || {});
                }
            }
        }
    }
    return targetObj;
}

Please note that this code is just off the top of my head, and is not tested in any way. It doesn't check for recursion, so it's not safe to use... but you get the gist of it, I hope.

Now, how could the code in your question alter the memory usage? Simple: JSON.stringify returns a string constant. This string has no binding to the original object any longer, so JS will allocate new memory to accomodate the memory for this string. Then, this string is being passed to JSON.parse. Again, a new object will be created, allocating memory for this object (that does not reference the original object) is required.
After assigning to ajaxdata3, the GC (GarbageCollector) kicks in. It'll find 2 references to a single object, so that object can't be GC'ed. It'll also register a second object, which is being referenced by the variable ajaxdata3, so that object, too, will remain in memory.
The return value of JSON.stringify is found, too, only this time, the GC sees that this string constant isn't being referenced anywhere, and so it flags that section of the memory. The next time the GC starts up, it'll check all flagged bits of memory and deallocate them (free them for usage).

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149