| home / programming / javascript / ncz / column4 / 1 | [previous] |
|
|
The iterative methods all have one thing in common: they run a given function on every item in an array. These functions must be in the following format:
function func_name(vValue, iIndex, aArray) {
//code goes here
}
When a function is passed into one of these iterative methods, three arguments are passed in the array item, the index of the item within the array, and the array itself. Depending on how you're using the function, this should be all the information you'll ever need.
To elaborate, let's say that you want to know if one or more of the items in an array meets some specific criteria. In this case, let's suppose that you'd like to know if any number in an array is over 90. You'd define a function like this:
function isOver90(vValue, iIndex, aArray) {
return vValue > 90;
}
You can pass this function into the some() method, which returns
true if the given function returns true for any one item in the array:
var aNumbers = [56, 43, 23, 94, 32, 91];
if (aNumbers.some(isOver90)) {
alert("There's at least one number over 90");
} else {
alert("There are no numbers over 90");
}
If you want to know if all numbers in the array are over 90, you need to use
the every() method in the same way. The every() method
returns true only if the function returns true for every item in the array:
var aNumbers = [56, 43, 23, 94, 32, 91];
if (aNumbers.every(isOver90)) {
alert("All numbers are over 90");
} else {
alert("All numbers are not over 90");
}
It helps to think of some() as a logical OR and every()
as a logical AND. With these two methods, you can determine if there are any
numbers over 90 in the array, but how can you get those numbers? This is where
the filter() method comes in.
The filter() method runs a function on every item in the array
and, if the function returns true, adds the value to a result array. In this
way, you can extract items that meet certain criteria without doing it manually.
To retrieve all numbers over 90 in the array, you can do this:
var aNumbers = [56, 43, 23, 94, 32, 91];
if (aNumbers.some(isOver90)) {
var aOver90Numbers = aNumbers.filter(isOver90);
alert("The numbers over 90 are " + aOver90Numbers);
} else {
alert("There are no numbers over 90");
}
In this example, the aOver90Numbers array will contain 94 and
91, the only two numbers greater than 90 in the aNumbers array.
Note that the same function, isOver90(), was used for both some()
and filter() in this code. This represents the true power of these
new methods.
How often do you use a for loop to work with items in an array? Well, with
forEach(), you might not ever need to write another for loop again!
Okay, that may be a bit of an exaggeration, but that's the basic idea behind
forEach(). Unlike the other iterative methods, this one doesn't
return any value; its sole purpose is to run the same code on every item in
the array. If you want to do something such as printing out all the items in
an array, you could do this:
function printOut(vValue, iIndex, aArray) {
document.writeln(vValue + "<br />");
}
var aNumbers = [56, 43, 23, 94, 32, 91];
aNumbers.forEach(printout);
This code outputs each item in the array to the page. It's important to keep
in mind that you can't return a value through the function in this case, but
what if you want to perform the same operation on each item in the array and
get the results? That's when the map() method comes in handy.
The map() method executes a function on each item in an array
and stores the results in another array. This comes in handy when you need to
perform mathematical functions on entire arrays. Here's a simple example:
function timesTwo(vValue, iIndex, aArray) {
return vValue * 2;
}
var aNumbers = [4, 2, 6, 9];
var aTimesTwoNumbers = aNumbers.map(timesTwo);
After executing, aTimesTwoNumbers contains 8, 4, 12, and 18. Note
that the item in position 0 in aTimesTwoNumbers is the result of
executing the function on the item in position 0 in aNumbers. This
way, you can correlate information from the resulting array with the original
array.
All of the examples to this point have used standalone functions passed in to the iterative methods. There is an optional second argument for all of these methods that specifies the context in which to execute the function. In plain terms, this allows you to use object methods. Suppose you have the following object:
var oCalc = new Object();
oCalc.base = 2;
oCalc.factor = 5;
oCalc.isGoodNumber = function (vValue, iIndex, aArray) {
return (vValue % this.base == 0);
};
oCalc.fixValue = function(vValue, iIndex, aArray) {
return vValue * this.factor;
};
This object, while very simple, uses the base and factor
properties to complete calculations in each method. In isGoodNumber(),
a value of true is returned when the value is equally divisible by base
(2); in fixValue(), the value is multiplied by factor
(5). To use oCalc, you may try doing this initially:
var aNumbers = [4, 2, 6, 9];
if (aNumbers.some(oCalc.isGoodNumber)) {
var aGoodNumbers = aNumbers.filter(oCalc.isGoodNumber);
var aNewNumbers = aGoodNumbers.map(oCalc.fixValue);
}
The intent of this example is to get all the numbers that are equally divisible
by 2 and then multiply those numbers by 5. The problem here is that there is
no context for the isGoodNumber() or fixValue() methods.
When taken as standalone functions (which this example does), isGoodNumber()
always returns false because this.base evaluates to
nothing, which makes the calculation equivalent to NaN.
Therefore, the if statement prevents further calculation. To fix
this, just add the context object:
var aNumbers = [4, 2, 6, 9];
if (aNumbers.some(oCalc.isGoodNumber, oCalc)) {
var aGoodNumbers = aNumbers.filter(oCalc.isGoodNumber,
oCalc);
var aNewNumbers = aGoodNumbers.map(oCalc.fixValue, oCalc);
}
Now this example works as expected.
Mozilla's new Array methods are a welcome addition to JavaScript
as a whole. With very few changes to the language (over the past few years),
these methods are significant in their meaning: Mozilla believes in JavaScript
and is looking towards how it can be made into a better language for Web developers.
The down side is that we need to wait until Firefox 1.5 is released (now scheduled
for September 2005).
In the meantime, you'll need to use a JavaScript library to emulate these new
methods. I have created a library
that adds the methods to the Array object in all browsers, as has
Erik Arvidsson. Using
either library, you'll need to make sure the JavaScript file is loaded before
attempting to use any of the new methods.
Nicholas C. Zakas is a user interface designer for Web applications and the
author of Professional
JavaScript for Web Developers (Wiley Press, ISBN 0764579088). Nicholas can
be contacted through his Web site, http://www.nczonline.net/,
where he provides open source JavaScript libraries and tools.
| home / programming / javascript / ncz / column4 / 1 | [previous] |
Created: March 27, 2003
Revised: August 12, 2005
URL: http://webreference.com/programming/javascript/ncz/column4/1