Mark Needham

Thoughts on Software Development

Reading Code: underscore.js

with 9 comments

I’ve been spending a bit of time reading through the source code of underscore.js, a JavaScript library that provides lots of functional programming support which my colleague Dave Yeung pointed out to me after reading my post about building a small application with node.js.

I’m still getting used to the way that JavaScript libraries are written but these were some of the interesting things that I got from reading the code:

  • There are a couple of places in the code where the author has some code which runs conditionally and this is achieved by including that expression on the right hand side of an ‘&&’.

    For example on line 129 in the ‘filter’ function:

    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    
      // Return all the elements that pass a truth test.
      // Delegates to JavaScript 1.6's native filter if available.
      _.filter = function(obj, iterator, context) {
        if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
        var results = [];
        each(obj, function(value, index, list) {
          iterator.call(context, value, index, list) && results.push(value);
        });
        return results;
      };

    I would probably have used an if statement to check the result from calling ‘iterator’ but this way is more concise and pretty neat.

    The same type of thing is done on line 150 in the ‘every’ function:

    145
    146
    147
    148
    149
    150
    151
    152
    153
    
      _.every = function(obj, iterator, context) {
        iterator = iterator || _.identity;
        if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
        var result = true;
        each(obj, function(value, index, list) {
          if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
        });
        return result;
      };

    The result is collected and the loop will also exit if the value of ‘result’ is ever false which is again a cool way to organise code.

  • It’s also quite cool that you can assign a value to a variable from within a conditional – this isn’t possible in any of the other languages that I’ve used previously as far as I’m aware.

    It’s even more evident in the ‘max’ function:

    191
    192
    193
    194
    195
    196
    197
    198
    199
    
      _.max = function(obj, iterator, context) {
        if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
        var result = {computed : -Infinity};
        each(obj, function(value, index, list) {
          var computed = iterator ? iterator.call(context, value, index, list) : value;
          computed >= result.computed && (result = {value : value, computed : computed});
        });
        return result.value;
      };

    ‘result’ is conditionally assigned on line 196 but only if the computed value is greater than the current computed value. Again an if statement is avoided.

    Another interesting thing about this function is that it specifically checks the type of the ‘obj’ passed in which reminded me about the discussion around Twitter having those sorts of checks in their Ruby code around a year ago. I guess that type of thing would be more prevalent in library code than in an application though.

  • I hadn’t come across the !! construct which is used to turn a JavaScript expression into its boolean equivalent:
    506
    507
    508
    
      _.isArray = nativeIsArray || function(obj) {
        return !!(obj && obj.concat && obj.unshift && !obj.callee);
      };

    Without using ‘!!” the expression would return ‘undefined’ in the case that one of those functions on ‘obj’ was not set. ‘!!’ forces the return value to be ‘false’.

  • Another technique used in this code base is that of dynamically adding methods to the prototype of an object:
    666
    667
    668
    669
    670
    671
    672
    673
    
      // Add all mutator Array functions to the wrapper.
      each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
        var method = ArrayProto[name];
        wrapper.prototype[name] = function() {
          method.apply(this._wrapped, arguments);
          return result(this._wrapped, this._chain);
        };
      });

    This is quite a cool use of meta programming although it isn’t initially obvious how those functions end up on the object unless you know what to look for. It does significantly reduce the code needed to add these functions to the ‘wrapper’ object’s prototype, avoiding the ‘same whitespace, different values‘ problem that Neal Ford outlines in his article about harvesting idiomatic patterns in our code.

Be Sociable, Share!

Written by Mark Needham

March 28th, 2010 at 8:02 pm

Posted in Reading Code

Tagged with

  • && is available in C# too (so is ||).

    The assigning of a variable in a condition is using an inline if statement, which means you can do the same thing (demo below)

    Inline conditions:
    static void Main(string[] args)
    {
    bool test = false;
    bool result = false;

    if (result = (result ? test : true))
    {
    Console.WriteLine(“Should only show if result is true”);
    }

    Console.WriteLine(result);
    }

  • Ah cool I didn’t know you could assign a variable inline like that. Still can’t decide whether it’s more or less readable written that way!

  • I think it’s definitely less readable in C#. It’s also not terribly useful, since you’re restricted to boolean types in conditional tests.

    JavaScript will let you test if the value is “falsy,” which is nice because it allows you to use this idiom as a guard clause to see if a var is initialized.

    This idiom is also common in C for testing a pointer for nullity.

    Bottom line, I think you should avoid it in C# just because people won’t expect to see it. Match your style to the culture of the language. Just my two cents.

  • dm3

    Actually there’s nothing special about the !!. As javascript is weakly typed, first application of ! converts the value its applied to to boolean, as in
    !1 == false or !undefined == true. The second application negates the result and that’s it.
    But you probably know that already )

  • “Assignment in a conditional” is pretty common, but many language cultures don’t use it because of the mistakes it can hide:

    if (shouldDeleteEverything = true) {
    deleteEverything();
    }

    That’s valid in a lot of languages, but doesn’t do what it seems to so compilers and style checkers warn against it.

    It’s a syntax error in Python for much the same reason.

  • @dm3 actually nope I hadn’t picked up that’s what was happening, thanks for pointing that out!

  • Pingback: Ruby: Control flow using ‘and’ at Mark Needham()

  • Pingback: Mark Needham: Ruby: Control flow using ‘and’ | Software Secret Weapons()

  • Pingback: Reading Code: boilerpipe at Mark Needham()