Q: Returning a closure's variable is creating a copy instead of a reference I'm confused by this closure behavior. I've read several SO articles (including this one) and MDN's documentation on closures, but haven't seen the explanation for this behavior.
In the code sample below I'm creating a closure containing a variablecache, a function preload that modifies it, and a function report that logs its value. It also attaches references to those to an object that is passed in.
'use strict';

var o = {};

(function(obj) {
    var cache = {'initialized': false};

    function preload(assets, done) {
        console.log('Preloading. Value of cache is', cache);
        cache = {};

        for (var i = 0; i < assets.length; i++) {
            cache[assets[i]] = assets[i];
        }
    }

    function report() {
        console.log('Cache from inside is ', cache);
    }

    function get_cache() {
        return cache;
    }

    obj.cache = cache;
    obj.preload = preload;
    obj.report = report;
} )(o);

// {initialized: false}, as expected
o.report();

// {initialized: false}, as expected
console.log('Cache from outside is ', o.cache);

// I expect this to change cache to {1:1, 2:2, 3:3}
o.preload([1, 2, 3]);

// {1:1, 2:2, 3:3}, as expected
o.report();

// {initialized: false}, NOT as expected. Why?
console.log('Cache from outside is ', o.cache);

My expectation is based on my understanding that when the closure attaches cache to the provided obj, it is assigning a reference to the variable within the closure. But the behavior I'm seeing suggests that obj.cache is getting a copy of the closure's cache.
At which point is a copy of cache created and why?

A: When you call obj.cache = cache; in the beginning, you are making obj.cache points to the same object that cache is pointing to (This object: {'initialized': false})
Then later when you call preload, you point the variable cache to another, new object: cache = {};. Now the cache variable is pointing to a brand new object, while obj.cache still point to the old object that was created in the beginning.
That explain why all log done on cache inside the closure logs new values, while logging obj.cache still show unchanged values. They're now pointing to 2 different objects, and changing the content of the object that cache is now pointing to have no effect on the original object has obj.cache is pointing to.

A: At the time your IIFE got executed, you have added cache to obj.cache and that was that. obj.cache doesn't hold a reference to the cache variable from your IIFE. But, report and preload functions are using cache variable from your IIFE, even as they are invoked outside of the scope where they have been created. As such, reference to the scope inside your IIFE is being preserved for obj.preload and obj.report functions (this is where closure is being observed), but not for obj.cache.
For more details on various situations how closure is being observed and exercised, please check out this link.
