Select to view content in your preferred language

Stop using dojo/_base/array

2527
8
12-24-2014 07:03 AM
Labels (1)
ReneRubalcava
Esri Frequent Contributor
1 8 2,527

stop_array.jpg

A long time ago, when web browsers were powered by gremlins and gnomes, we used to have to use JavaScript frameworks for the simplest of tasks. The most essential methods of objects such as the Array were in their infancy.

You used to have to write loops manually, such as this:

for (var i = 0; i < myArray.length; i++) {
  // do something
}

The horror. Then JavaScript developers were give a gift. The gift of iteration methods, such as map, filter, some and more. This greatly simplified how we could write code... unless you had to support Internet Explorer 8 and below. But before there was even an Internet Explorer 8, libraries like Dojo provided utilities to mimic these functions before they were finalized. This is where dojo/_base/array provided magical methods when we had to support browsers like Internet Explorer 6. Times were looking brighter.

That was a long time ago. Browsers have come a long way. In my experience, even in government infrastructures, Internet Explorer 9 has become the minimum requirement I need to worry about. Dojo 2.0 is on the horizon (somewhere) and even in their own docs for dojo/_base/array it is stated:

In Dojo 2.0, this module will likely be replaced with a shim to support functions on legacy browsers that don’t have these native capabilities.

Emphasis is my own. What does that mean? That means you should stop using dojo/_base/array. That's how I'm reading it and I'm sticking to it. Do you still need to support Internet Explorer 8 and below? Use a shim/polyfill. Start writing your iterations like this:

// get the attributes of all features
var onlyAttributes = features.map(function(feature) {
  return f.attributes;
});

// find features with acreage greater than 500
var myFeatures = features.filter(function(feature) {
  return feature.attributes.ACRES > 500;
});

// add graphics to the map
features.forEach(function(feature) {
  this.map.graphics.add(feature);
}.bind(this)); // bind() is how you can pass context to functions

// find features with greater than 500 acres and get only the attributes
var myAttributes = features.filter(function(feature) {
  return feature.attributes.ACRES > 500;
}).map(function(feature) {
  return feature.attributes;
});

// get the first result of an address search
var address = addressCandidates.map(function(result) {
  return result.address;
}).shift();

We should be incredibly grateful for dojo/_base/array and what it brought us as JavaScript developers in our time of need. But I'm pretty confident that time is behind us.

When should I use dojo/_base/array?

Ok, so there is a case when dojo/_base/array would be the only way to iterate an array, actually array-like objects, like arguments.

For example:

var func1 = function() {
  arrayUtils.forEach(arguments, function(arg) {
    console.debug(arg);  
  });
};

func1(1,2,3,4); //-> 1,2,3,4

var func2 = function() {
 arguments.forEach(function(arg) {
    console.debug(arg);  
  });
};

func2(1,2,3,4); //-> throws error

This happens because although arguments is an array-like object that contains the arguments passed to a function, it doesn't have all the sugar a true Array has. But let's be honest here, were you really doing this? Probably not. It's typically best to avoid this behavior if you can. But if you really needed to, there is an easy way to do this.

var func3 = function() {
  [].forEach.call(arguments, function(arg) {
    console.debug(arg);
  });
};

Magic!

To summarize:

  1. Use a polyfill if you want to play it safe.
  2. Use native Array iteration methods
8 Comments
JeffJacobson
Frequent Contributor

Good advice.

stevegourley
Frequent Contributor

Native methods aren't always faster...

native vs lodash · jsPerf

JeffJacobson
Frequent Contributor

2014-12-24 08_37_03-Clipboard.png

stevegourley
Frequent Contributor

silly firefox. well, native methods aren't always faster on every browser. They also don't have feature parity with the 3rd party implementations. Anything lazy would be much more noticeable. Either way, here's a grain of salt.

ReneRubalcava
Esri Frequent Contributor

Reverse while loops are sometimes the fastest overall, it all depends on the browser.

On a side note, lo-dash has been part of the dojo foundation for a couple of years.

Sizzle - The Dojo Foundation

I don't know if that means we'll see some lo-dash in the future of dojo, but that would be interesting.

ReneRubalcava
Esri Frequent Contributor

Also the arguments in dojo/lodash/jquery for iterators are not in ideal order for composition.

So you can't do this.

var sqrMap = libraryOfChoice.map(function(x) { return x*x; });

sqrMap([1,2,3,4]);

But that's beside the point. If I were to use a third-party utility for arrays and overall functionality, I'd go with Ramda. or a combo of Ramda & lodash modules since you can load custom lodash builds.

KenDoman
Frequent Contributor

Great advice,

Last year, I made it a goal to remove dojo/_base/lang from my applications. Most notably, to replace lang.hitch() with Function.prototype.bind(). Of course, I had to polyfill because we support IE 8 & 9. This year, I'll make it a goal to remove dojo/_base/array as well.

JeffPace
MVP Alum

IE8 is still in major use, and we still have to support back to IE7 (government), although that is waning.  IE8 will be here for at least 5 more years.

Dropping support is unrealistic.

About the Author
Softwhere Developer at Esri working on cool stuff! Author: Introducing ArcGIS API 4 for JavaScript: Turn Awesome Maps into Awesome Apps https://amzn.to/2qwihrV ArcGIS Web Development - https://amzn.to/2EIxTOp Born and raised in East L.A.