Activate your free membership today | Log-in

Tuesday, May 5th, 2009

A Better Javascript Memoizer

Category: JavaScript, Performance

<p>We have covered memoizers in the past, but John Hann has posted on a nice implementation that takes advantage of closures, arity, and recursion -- 3 concepts/features that Javascript was meant to use.

It leads to this generic version:

JAVASCRIPT:
  1.  
  2. // memoize: a general-purpose function to enable a function to use memoization
  3. //   func: the function to be memoized
  4. //   context: the context for the memoized function to execute within
  5. //   Note: the function must use explicit, string-serializable parameters
  6. function memoize (func, context) {
  7.     function memoizeArg (argPos) {
  8.         var cache = {};
  9.         return function () {
  10.             if (argPos == 0) {
  11.                 if (!(arguments[argPos] in cache)) {
  12.                     cache[arguments[argPos]] = func.apply(context, arguments);
  13.                 }
  14.                 return cache[arguments[argPos]];
  15.             }
  16.             else {
  17.                 if (!(arguments[argPos] in cache)) {
  18.                     cache[arguments[argPos]] = memoizeArg(argPos - 1);
  19.                 }
  20.                 return cache[arguments[argPos]].apply(this, arguments);
  21.             }
  22.         }
  23.     }
  24.     // JScript doesn't grok the arity property, but uses length instead
  25.     var arity = func.arity || func.length;
  26.     return memoizeArg(arity - 1);
  27. }
  28.  

and this conclusion:

Yes, memoization is a neat concept. But why use it rather than just hand-coded caching mechanisms? It’s easy enough to write a caching routine, right? Here are a few good reasons:

  • hand-coded caching mechanisms obfuscate your code
  • multi-variate caching routines are bulky in Javascript
  • fewer lines of code means fewer bugs
  • Java programmers will think more highly of you ;)

Related Content:

  • Using Terracotta DSO
    Terracotta DSO is an open source technology created by Terracotta, meant to provide clustering to Java at the virtual machine level. It does so by...
  • Microsoft works on Ajax JavaScript tools
    In a session at the recent Ajax Experience conference in San Francisco, Matt Gibbs, development manager in the UI Framework and Services team at...
  • Caching Scenarios
    Caching is a quick and easy way to save roundtrips between your application and where you store your data. However, it’s not as easy as just...
  • Chapter 22: JavaScript security
    JavaScript continues to find adherents. But this scripting language can be used by malicious hacks to eat up memory .. and worse. Learn about Java...
  • Ajax seen solving JavaScript issues for RIA
    For rich Internet application (RIA) development, Ajax is doing for JavaScript what JavaScript couldn't do alone, the author argues. "The browser wars...

Posted by Dion Almaer at 5:16 am
4 Comments

++++-
4.1 rating from 30 votes

4 Comments »

Comments feed TrackBack URI

Wondering why he used func.arity || func.length instead of just func.length. Mozilla Developer Center marks Function.arity as deprecated.
Nitpicking anyway.

Comment by igstan — May 5, 2009

I coded a memoization function that works with non-unary functions some time ago (last year actually):

http://blog.thejit.org/2008/09/05/memoization-in-javascript/

I wonder what are the tradeoffs/benefits of using my memoization function and his.

Comment by philogb — May 5, 2009

I think that ‘Java programmers will think more highly of you’ is more of a negative than a positive :)

Comment by Sembiance — May 5, 2009

Hey igstan, thanks for alerting me to the fact that arity is deprecated. I have no idea why we’d want to deprecate the proper mathematical term. Go figure! :-)

@philogb: You’ve got a great article. Very in-depth discussion. I think the main difference between our implementations is that I am favoring recursion over serialization of multiple parameters (as yours implements). If I am in total control of the data that will be fed in as parameters, then I might not be so picky about serialization. However, my mind is always focused on componentization and code reuse. (I think it’s always a good idea to program defensively, too.) Therefore, I wanted to find a method that could work with any parameter data. I didn’t quite do it, but I feel I got further than any other implementation I’ve seen so far (in Javascript).

Comment by unscriptable — May 5, 2009

Leave a comment

You must be logged in to post a comment.