24
2011
On Dojo Array Functions and Good Beer
My dad is not a JavaScript programmer, but he does have something in common with nearly all of us; a deep and passionate love of beer. Unlike most JavaScripters, however, my dad’s favorite brew is on the lower-end of the quality spectrum. When he reaches for a cold one, he Heads for the Mountains. Yes, my dad’s favorite beer is Busch. This presents a problem when he makes the journey from Maine to North Carolina for a visit. Being the good son that I am, I make sure my fridge is stocked with a case upon his arrival. Inevitably though, he never finishes all of them before heading home. I can’t be certain, but I’m quite sure the first person to ever utter the phrase ‘You can’t give these things away!’ was faced with a Busch beer surplus . After his most recent visit, I turned to Facebook to help myself out…
I don’t want to brag or anything, but I have well over 100 Friends on Facebook. Would you believe not one of them took these fine beverages off my hands? There are some problems even Mark Zuckerberg can’t solve.
If Life Were Software
The other day, I was working on a Dojo-based project and was paring down a JavaScript array using the ultra-slick dojo.filter function. As I was effortlessly discarding the unwanted array elements, I had the thought, “Man, I really could have used dojo.filter when I was trying to get rid of those Busch beers!”. (Am I the only one that wishes for the ability to apply software-based solutions to our physical world? Surely I’m not the only person that gets an overwhelming urge to do a ctrl-f while hopelessly searching the aisles at Wal-Mart?). The revelation at the handiness of dojo.filter made me realize that the Dojo array functions deserve a blog post of their own. And what better contrived data set than an array of beers?
Some Silly Data
In this article, we will use the following array. It contains two Busch beers and an assortment of good beers. Each beer object contains two strings, one representing the brand of beer, and a second that contains a path to an image of that beer’s logo.
var beersData = [
{"brand":"Busch", "image":"images/busch.png"},
{"brand":"Blue Moon", "image":"images/bluemoon.png"},
{"brand":"Fat Tire", "image":"images/fattire.png"},
{"brand":"Stella Artois", "image":"images/stellaartois.png"},
{"brand":"Busch", "image":"images/busch.png"}
];
Note: I am of the extremely rare classification of JavaScript programmer that does not drink. Therefore, I have no idea if these beers are any good. I queried the most sophisticated of my IBM colleagues for their favorite beer and these names kept coming up, so I trust that they must represent the very best beers in the world.
dojo.forEach
We’ll begin our investigation of the Dojo array functions with a look at the workhorse dojo.forEach. It’s true that dojo.forEach is just a syntactically sugared version of a for-loop, but oh how sweet it is. In its simplest form, dojo.forEach is passed an array and a function that gets executed on each member of that array. The following code uses dojo.forEach to craft a function called beersToDOM which creates an img element for each beer in our array.
dojo.ready(function(){
var beersData = [
{"brand":"Busch", "image":"images/busch.png"},
{"brand":"Blue Moon", "image":"images/bluemoon.png"},
{"brand":"Fat Tire", "image":"images/fattire.png"},
{"brand":"Stella Artois", "image":"images/stellaartois.png"},
{"brand":"Busch", "image":"images/busch.png"}
];
var beersToDOM = function(beers, target) {
dojo.forEach(beers, function(beer){
dojo.create("img", {"src":beer.image}, target);
});
};
beersToDOM(beersData, dojo.byId('foreachDemo'));
});
This div has an id of foreachDemo.
It also bears noting that the arguments passed to dojo.forEach‘s callback function include two other parameters that I omitted from the above example. In addition to the current array element, the array index (“i value”), and a reference to the array itself are also passed. It is often-times helpful to have these bits of information while iterating over arrays. Here is the same forEach code with those arguments specified:
dojo.forEach(beers, function(beer, index, array){
dojo.create("img", {"src":beer.image}, target);
});
Another nifty feature of dojo.forEach is the optional scope parameter. Passing an object as the final argument to forEach results in the callback function being executed in the scope of that object. This means that the ‘this’ in the callback function will be the object you pass it.
dojo.forEach(array,
function(item, index, originalArray) {...},
obj); // Invokes the function in the scope of 'obj'
dojo.filter
dojo.filter looks much like dojo.forEach. Its arguments are an array and a function to run on each array member. dojo.filter returns a new array whose contents are determined by the boolean return value of its callback function. If true is returned for an individual array item, that item is included in the new array. If false is returned, that item is excluded. Look at how elegantly we can return a new array that contains none of the undesirable Busch beers.
var skunkFree =
dojo.filter(beersData,
function(beer){ return beer.brand != "Busch"; }
);
beersToDOM(skunkFree, dojo.byId('filterDemo'));
This div has an id of filterDemo.
dojo.map
Getting rid of the Busch beers was a solid accomplishment, but it would be much better if we could somehow transform them into good beers. For this Rumpelstiltskin-esque task, we’ll turn to dojo.map. dojo.map runs its callback function on every item in the array and creates a new array containing the return values of each invocation of the function. Let’s write a function that detects if an array item is a Busch beer. If so, we’ll return an object literal representing a Blue Moon. If the beer is not a Busch, we’ll return a copy of that perfectly-fine-as-it-is beer.
var beerAlchemy = dojo.map(beersData, function(beer) {
return beer.brand === "Busch" ?
{
"brand":"Blue Moon",
"image":"images/bluemoon.png"
} : dojo.clone(beer);
});
beersToDOM(beerAlchemy, dojo.byId('mapDemo'));
This div has an id of mapDemo.
dojo.some and dojo.every
Rounding out the Dojo Array functions are two simple functions that return boolean values. dojo.some returns true if some of the items in the passed array return true for the passed callback function. dojo.every returns true if all of the items in the passed array return true for the callback function. As a simple example, here is a function that does a sniff test to determine if the beer is a Busch. dojo.some returns true because there are two Busch beers in the array. dojo.every returns false because the array is not entirely composed of Busch beers.
var beersData = [
{"brand":"Busch", "image":"images/busch.png"},
{"brand":"Blue Moon", "image":"images/bluemoon.png"},
{"brand":"Fat Tire", "image":"images/fattire.png"},
{"brand":"Stella Artois", "image":"images/stellaartois.png"},
{"brand":"Busch", "image":"images/busch.png"}
];
var skunkTest = function(beer) {
return beer.brand === "Busch";
}
var hasSkunk = dojo.some(beersData, skunkTest); // TRUE
var nuthinButSkunk = dojo.every(beersData, skunkTest); // FALSE
Array functions, the key to cleaner code
Before discovering the array functions, many Dojo newcomers transitioning from Java or C# find themselves lost without formal ‘Collection’ types. It’s not long before things like function contains(array, object){...} are springing up all over the place. Writing helper-functions like this is a natural reaction, but almost always unnecessary. When used proficiently just about all array manipulation tasks can be completed using forEach, filter, map, some, or every. Mastering these functions will result in concise and readable array manipulation code, definitely something worth raising a glass to.
Related Posts
4 Comments + Add Comment
Leave a comment
Recent Comments
- Randy Hudson on Lessons in Widgetry: Binding Property Values to DOM Nodes in Templates
- James on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- Deepesh on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- RS on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- Dan Lee on From Springfield to Stuttgart, an Introduction to i18n with Dojo

An article by








Do you like the taste of beer?
dojo.forEach(beersData, function(beer) {
me.drink(beer);
});
I believe something like this also works and uses even less code
var skunkFree = dojo.filter(beersData, “return item.brand != ‘Busch’;”);
beersToDOM(skunkFree, dojo.byId(‘filterDemo’));
Regarding your dojo.forEach example, wouldn’t it be better to create all the elements and then add them at the end? (instead of create & add each in the loop)