Search code examples
javascriptecmascript-6closures

Is a closure a copy of the values to another position of memory?


I created the memoization bellow as a proof of concept. I wanted to discover the answer for the following question: When we modify a variable inside a closure, does it modify the original initial location in the memory? Or when a closure is created it copies all the values from the original location to another position in the memory? According to my test with the code bellow, it does a copy, but, the original location is also affected when the values inside the closure change. Test by yourself.

class Memoization { 
    cacheInitValue = new Map();
    memoize(f) {
        let cache = this.cacheInitValue;
        return function (...args) {
            let cacheKey = f.name + JSON.stringify(args);
            if (cache.has(cacheKey)) {
                return cache.get(cacheKey);
            }
    
            let result = f.apply(this, args);
            cache.set(cacheKey, result);
            return result;
        };
    }
}

// Example of use #1: memoize simple function
// ----------------------------------------------------------------

function sum(...numbers) {
    console.log(`sum(${numbers.join(',')}) was called`);
    let total = 0;
    for (let n of numbers) {
        total += n;
    }
    return total;
}

// using:

let memoSum = new Memoization();
let cacheSum = memoSum.memoize(sum);

console.log(cacheSum(10,20)); // get result from function (first time)
console.log(cacheSum(10,20)); // get result from cache

// Now,take a look in the object memoSum has it property modified by the closure:

console.log(memoSum.cacheInitValue, "(see browser console)"); // the output is the keys of map changed inside the closure context. 

// Now is the weirdest part, force a reset the cacheInitValue and see what happens:

memoSum.cacheInitValue = new Map();

// Yeah… call again the memoized:

console.log(cacheSum(10,20));


Solution

  • The problem isn't related to closures, you didn't overwrite cache.

    1. you assign initCacheValue to cache. The both variables now point to the same object.
    2. you change initCacheValue but that doesn't change cache. It still points to the old object.

    The reason: object variables are references to objects, not objects themselves.

    In your case resetting the cache could be:

    memoSum.cacheInitValue.clear();