Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I wanted an elegant way to implement memoizing. Here is what I came up with:

function memoize(fn) {
    var cache = new WeakMap();
    return function() {
        if (!cache[arguments]) {
            cache[arguments] =, arguments);
        return cache[arguments];

It's quite nice, but the WeakMap is not well supported. Is there a better, yet clean way to do this?

share|improve this question
You should use fn.apply instead of if you want to use the original arguments. – Elmer Nov 19 '15 at 10:56

I use this

function memoizeFirst(fn) {
    const cache = new WeakMap();
    return function(arg) {
        if (!cache.has(arg)) {
            cache.set(arg, fn(arg));
        return cache.get(arg);

this function will memoize the result of the function you pass and cache it. The cache will vary on the first argument, and only on the first argument. Do not use this function if you are planning on passing more then one argument to it! Do use this function if you want to pass an object as the first argument.

I use this function for building (temporary) indexes based on an immutable state. Example (the groupBy, where methods come from IxJS):

const getParentObjectIndex = memoizeFirst(state => state.objectSource && state.objectSource.
    where(objectItem => objectItem.parentObject).
    groupBy(objectItem => objectItem.parentObject).
    reduce(function(map, group) {
        map[group.key] = group.
        orderBy(item => item.position).
        return map;
    }, {})

Because the state is immutable, it will not change. The only way to change the state is to create a new one. So everytime something changes, we have a new state. That makes is an excellent cache key!

share|improve this answer

I just thought about this:

function memoize(fn) {
    var cache = {};
    return function() {
        var args =;
        if (!cache[args]) {
            cache[args] =, arguments);
        return cache[args];

It's very cross-browser. I can't think of any browser not supporting this.

But it does feel kind of ugly. It's still the best I can think of though.

share|improve this answer
This isn't equivalent. There can be collisions. For example, ["a,b"] and ["a", "b] (at least my understanding of Array.toString --…) – Corbin Feb 1 '13 at 19:06
Indeed. Then I'm lost :P – Florian Margaine Feb 1 '13 at 19:08
JSON stringifying would probably be wiser – megawac Aug 15 '14 at 0:21

Is there a better, yet clean way to do this?

"Better" and "clean" are both debatable. There's a way to do it, using JSON serialization.

But speaking to your current code, I'm not sure that maps would the trick. Every call to the function will result in a distinct arguments object (even if the individual arguments are the same), so I think you'd get "duplicate" keys. At least I imagine so. I don't have an up-to-date browser on this machine, so I can't test, and I haven't played enough with Map/WeakMap to know off-hand.

Besides, you need to use has() and set(); using [...] will, I believe, just set a regular property (which implies string coercion of the key).

Now, for alternatives, you could do something like what Addy Osmani's proposes (the entire article is worth a read). The basic idea is to use JSON.stringify() to serialize the arguments in a more robust way than toString.

I'll include it here, as-is:

* memoize.js
* by @philogb and @addyosmani
* with further optimizations by @mathias
* and @DmitryBaranovsk
* perf tests:
* Released under an MIT license.
function memoize( fn ) {
    return function () {
        var args =,
            hash = "",
            i = args.length;
        currentArg = null;
        while (i--) {
            currentArg = args[i];
            hash += (currentArg === Object(currentArg)) ? 
            JSON.stringify(currentArg) : currentArg;
            fn.memoize || (fn.memoize = {});
        return (hash in fn.memoize) ? fn.memoize[hash] : 
        fn.memoize[hash] = fn.apply(this, args);

Source: Faster JavaScript Memoization For Improved Application Performance

It's a pretty neat solution, though obviously not as clean as just using WeakMap (if indeed that would even work).

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.