Ext JS iterator functions

Ext JS has a number of handy iterator functions. Some, like Ext.each, you probably already know about, but there are a few others lurking around which can be useful in saving yourself a few lines of code. First, let’s recap Ext.each:

Ext.each

Ext.each applies a function to each member of an array. It’s basically a more convenient form of a for loop:

var people = ['Bill', 'Saul', 'Gaius'];

//using each to detect Cylons:
Ext.each(people, function(person, index) {
  var cylon = (index + 1) % 2 == 0; //every second man is a toaster
  alert(person + (cylon ? ' is ' : ' is not ') + 'a fraking cylon');
});

//is the same as
for (var i=0; i < people.length; i++) {
  var person = people[i];
  var cylon = (i + 1) % 2 == 0; //every second man is a toaster

  alert(person + (cylon ? ' is ' : ' is not ') + 'a frakin cylon');
};

Ext.iterate

Ext.iterate is like Ext.each for non-array objects. Use it wherever you would normally use a for .. in loop:

var ships  = {'Bill': 'Galactica', 'Laura': 'Colonial One'};

Ext.iterate(ships, function(key, value) {
  alert(key + "'s ship is the " + value);
});

//is the same as
for (key in ships) {
  var value = ships[key];
  alert(key + "'s ship is the " + value);
}

Using Ext.iterate with an array is the same as calling Ext.each. Each and Iterate both take an optional third parameter, which is the scope to run the function in. Another advantage over using the for construct is that you can easily reuse the same function:

var myFunction = function(item, index) {
  //does some clever thing
}

Ext.each(people, myFunction);
Ext.each(['another', 'array'], myFunction);

Ext.pluck

Ext.pluck grabs the specified property from an array of objects:

var animals = [
  {name: 'Ed', species: 'Unknown'},
  {name: 'Bumble', species: 'Cat'},
  {name: 'Triumph', species: 'Insult Dog'}
];

Ext.pluck(animals, 'species'); //returns ['Unknown', 'Cat', 'Insult Dog']
Ext.pluck(animals, 'name'); //returns ['Ed', 'Bumble', 'Triumph']

Ext.invoke

Invoke allows a function to be applied to all members of an array, and returns the results. Using our animals object from above:

var describeAnimal = function(animal) {
  return String.format("{0} is a {1}", animal.name, animal.species);
}

var describedAnimals = Ext.invoke(animals, describeAnimal);
console.log(describedAnimals); // ['Ed is a Unknown', 'Bumble is a Cat', 'Triumph is a Insult Dog'];

Ext.invoke performs a similar job to Ruby’s collect method in making it easy to transform arrays. Any additional arguments passed to the Ext.invoke call will be passed as arguments to your function, in this case the describeAnimal function. Obviously your functions will be much more grammatically accurate than mine.

Ext.partition

Ext.Partition splits an array into two sets based on a function you provide:

var trees = [
  {name: 'Oak',    height: 20},
  {name: 'Willow', height: 10},
  {name: 'Cactus', height: 5}
];

var isTall = function(tree) {return tree.height > 15};

Ext.partition(trees, isTall);

//returns:
[
  [{name: 'Oak', height: 20}], 
  [{name: 'Willow', height: 10}, {name: 'Cactus', height: 5}]
]

The partition call above returns a 2-dimensional array with the first element containing all of the items for which the function returned true (tall trees in this case), and the second containing items for which the function return false.

Math functions

Finally, we have some simple math-related functions:

var numbers = [1, 2, 3, 4, 5];
Ext.min(numbers); //1
Ext.max(numbers); //5
Ext.sum(numbers); //15
Ext.mean(numbers); //3

While the built in functions don’t cater for all situations, they’re useful to have and to know about, and usually offer a more elegant approach than using the ‘for’ keyword.

22 Responses to Ext JS iterator functions

  1. Steffen Hiller says:

    Nice post, too! ;)Didn't know all of those methods.Which I don't like about these methods is the fact, that Ext doesn't add those methods to the object classes you perform those methods on. So, this is pretty much PHP style.I like more Prototype JS's and therefore Ruby's approach to add methods as 'each' directly to the Array class, which allows you to write [1, 2].each().That's why I actually like to use Ext JS with the Prototype JS adapter.I guess I'll write an Ext extension one day that adds such 'shortcuts' for the Ext methods to their respective class and removes the need for the Prototype JS dependency in my applications. Shouldn't be a big thing.

  2. Edward Spencer says:

    I also prefer Ruby's style of chaining method calls together, but sadly it can't be done safely in JavaScript, as augmenting Object breaks the "for key in values" construct.I think it can be ok to do that, so long as the implications are understood. I tend to stick to the side of caution though and not augment Object at all. Ext JS is very good at respecting that approach also.If you do write the extension you mention, be sure that everyone using it understands what the implications are :)

  3. rob says:

    Strictly speaking, nobody should mess around with JavaScript Object. Leave it as is.
    ExtJS approach is more professional.

  4. mike says:

    I’m wondering why Ext adds the single `remove` method to Array.prototype? Extending Array or Function is safer than extending Object w/ respect to `for in`, but is a bit invasive for a library to do. There’s a case for a really developer-friendly library like prototype to make enumeration easier, but that’s not Ext so why pollute Array for just a single method? Is this just a mistake from the early days?

  5. Ed Spencer says:

    @rob agreed – for clarity I was referring to the style of code produced with Ruby’s built in enumerable functions, it’s secondary to global object pollution concerns though.

    @mike as you say, augmenting Array is safe compared to augmenting Object because you don’t run ‘for … in’ on an array (unless you’re crazy). I’m not sure when it was added in but can’t really see a problem with it. Not sure I’d call it a ‘mistake’ either if it doesn’t have the negative consequences that augmenting Object has.

  6. Jluc says:

    Always excellent to read pages like this. Bright & helpful! Thanks a lot

  7. bbp says:

    Ext JS add a “remove” function that must be ignored.
    The Ext.each and Ext.iterate will not give the same result
    if an arbitrairy element is added in the array.

    ex:

    layers["layer1", "layer2"];
    layers[1000] = "layer3";
    layers["special"] = "layer4";

    With “Ext.each” and “Ext.iterate”, this will output the
    first 2 layers following by 998 undefined and the
    1000th layer. The “special” layer will be ignored.
    With the “for (i in layers)”, it will give the
    4 layers, but also the “remove” function added by
    Ext JS.

  8. bbp says:

    Here is the code I’m using to see the content of the array without all unwanted Undefined:

    for (i in layers) {
    if (i != 'remove') {
    layer = layers[i];
    // Do something with the layer
    }
    }

  9. srija says:

    Thanks alot… after 2 days struggle with my code i got the solution with this site.
    Thank you…

  10. Thank you for your post. I am a big Extjs fan and if all the best things were in the same framework it would be as great as all the best things were in all of us. What I know about Ext is, that you have to study hard but you will be rewarded for your efforts. Useless to compare it with another framework on the wrong arguments. Jquery is for “things” and Ext is for applications.

  11. Illop says:

    Quite hopeless to port an exsisting webapplication to extjs, when fully functional javascript code stop working because of extjs added array functions, well we decided not to use extjs on the project – The more i work with extjs, the less i like it.

  12. Ed Spencer says:

    @Illop I hope we win you back round with Ext JS 4. We’ve removed all native object augmentation

  13. I just started watching Battlestar Galactica on NetFlix.. Love the reference…

  14. Neil says:

    This is a great article! I keep coming back, very useful.

    One thing I also think that would be worth mentioning in this article is that Extjs each won’t handle break (or continue) like normal javascript, so instead you should use return false; (to break) or return true; (to continue)

  15. Aggie says:

    @Ed Spencer, this a very great article, thank you!!

  16. Pingback: extjs中の迭代だった | テクニカルブログ

  17. Pingback: The Extjs iteration

  18. Amy says:

    @Ed Spencer, excellent article, as always. Your examples are really helpful. Thanks!

  19. Nice post!
    Typo on Ext.each line 12, instead of (index + 1) should be (i+1)

  20. Ed Spencer says:

    Thanks Ronald, fixed

  21. Brandon says:

    This is a great post! Thank you.

  22. SimoAmi says:

    The description on Ext.invoke() is inaccurate and the corresponding example doesn’t work. The 2nd arguments which is a method name is supposed to be a member of each element in the array, whereas in your example it implies that the methodName can be an external method you can define separately.

    Ext.invoke([el1, el2], ‘enable’);

    means that you can also do it manually as:

    el1.enable();
    el2.enable();

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,601 other followers

%d bloggers like this: