Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at cf.Objective() 2013 (Bloomington, MN) with: Brad Wood
Ben Nadel at cf.Objective() 2013 (Bloomington, MN) with: Brad Wood@bdw429s )

Using Array Comprehensions in Javascript 1.7

By Ben Nadel on

After experimenting with list comprehensions yesterday in the context of ColdFusion, I thought I would take a look at array comprehensions in Javascript 1.7. As far as I know, array comprehensions are only supported by the newer versions of Firefox (2+). And, in order to use them, you have to denote the version of Javascript within your Script tag mime-type (to be safe).

As a refresher, a list / array comprehension is a way to create a new collection based on one or more existing collections. The comprehension creates a cross-product of the existing collections, filters it by the provided guard statements, and then allows you to define the new collection based on the individual value combinations.

To explore this in Javascript, I tried to take the ColdFusion example from yesterday and recreate it in Firefox:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Array Comprehensions in Javascript 1.7 - Mozilla</title>
  • <script type="text/javascript;version=1.7">
  • // Create a list of girls.
  • var girls = [ "Sarah", "Tricia", "Kit", "Joanna" ];
  • // Create a list of equations.
  • var equations = [ "is", "is not" ];
  • // Create a list of adjectives.
  • var adjectives = [ "hot", "awesome", "sexy" ];
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // Use new Array comprehensions to merge the three arrays
  • // into a new array.
  • var collection = [
  • (name + " " + equation + " so " + adjective + "!")
  • for each (name in girls)
  • for each (equation in equations)
  • for each (adjective in adjectives)
  • if (name != "Kit")
  • ];
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // Iterate over the collection to output the values.
  • for (var i in collection){
  • // Output the statement.
  • console.log( collection[ i ] );
  • }
  • </script>
  • </head>
  • <body>
  • <!-- Left intentionally blank. -->
  • </body>
  • </html>

As you can see, we have three existing collections: name, equations, and adjectives. Then, we are using the Javascript 1.7 array comprehension functionality to create our new array, "collection." The comprehension is composed of an assignment statement, three "for each" statements," and a single guard condition. When we run the above code, we get the following console output:

Sarah is so hot!
Sarah is so awesome!
Sarah is so sexy!
Sarah is not so hot!
Sarah is not so awesome!
Sarah is not so sexy!
Tricia is so hot!
Tricia is so awesome!
Tricia is so sexy!
Tricia is not so hot!
Tricia is not so awesome!
Tricia is not so sexy!
Joanna is so hot!
Joanna is so awesome!
Joanna is so sexy!
Joanna is not so hot!
Joanna is not so awesome!
Joanna is not so sexy!

As you can see, the resultant collection contains the filtered cross-product of our three existing arrays.

I don't know about you, but when I see this kind of stuff and I just get giddy! There is something deeply satisfying about being able to transform lists with such a low amount of effort.

Reader Comments

It might be powerful, but it doesn't read very well to me when compared with more common uses of JS. It looks more like Clojure with all those parentheses...


I am not sure. I think that once you get use to reading this, it might be easier to read. Although, I question the necessity of the "for each" portion of the statement. It seems like those could have quite easily been cut out with the same parsability. Although, I suppose since there are no statement delimiters (like there are in other languages that have comprehensions), these extra statements sort of act like delimiters.


And in JavaScript-related news, jQuery 1.5 was released Monday night.

Its principal features are a rewrite of AJAX handling, a new way to subclass jQuery and a significant speed-up of sequential DOM traversal, i.e., .children(), .next() and .prev(). (The release notes have the usual bar graphs by browser we've come to expect.)

It certainly seems peppier.

If you read John Resig's 1/20 post "Learning from Twitter" on, you know that using a context-appropriate DOM method (if available) results in a significant speed-up. I can't think of any way that observation could have helped speed up .children(), .next() and .prev() however, which is very, very good in retrospect. The bar graphs were relative to 1.4.4, not 1.4.2. It would have been sneaky to claim a speed-up for getting rid of a slow-down, and it appears that they didn't do that.

And THAT suggests a possible unclaimed improvement: If John's asserted back-port made it into 1.5, then .find() is back to being as fast as 1.4.2 used to be with regard to class and tag selectors. (I haven't had time to analyze the uncompressed version for evidence of the back-port, hence the "possible" and "if".)

I freakin' love jQuery. A truly shining example of what FOSS can and should be.

So, was considerably slower than a regular for. I wonder if for each is going to be equally slow.

MDC is using var inside the for each

I know they don't give a lot of details, but I'm wondering the readability of such syntax. Other languages that have different scoping mechanics than JavaScript can get away with this kind of syntax. We'll have to watch name collision inside our function with these, unless of course they decide to make the for..each constructor part of the scope (I think not).