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: http://bit.ly/q3zpG3
* Released under an MIT license.
*/
function memoize( fn ) {
return function () {
var args = Array.prototype.slice.call(arguments),
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).
fn.apply
instead offn.call
if you want to use the original arguments. \$\endgroup\$