Fred
Brack Raleigh, NC |
This is not a full tutorial on JavaScript arrays but rather an introduction and reference to their basic features and how to manipulate them. Want more detail? Try Learn-JS, which helped me; and my favorite reference site is W3Schools. I created this web page to help me document my understanding of JavaScript arrays as I progressed from novice to intermediate user ... and because I like to document stuff for others! I hope you find it useful.
Arrays are a special kind of object (which are discussed on my objects page). Rather than define named values (as in regular objects), you just specify the values themselves. To make the distinction for an array during definition, you use brackets instead of braces (used for objects), and you separate values by commas. Example:
var carModels = [ "Ford", "Chevrolet", "Dodge" ];
... and you reference the specific value via its index (which starts at 0) -- in other words, a number, not a property name (as in an object). Thus, carModels[1] is "Chevrolet"; and you could change that value if you want:
carModels[1]; // = "Chevrolet" carModels[-1] // = "Dodge", because "-1" refers to the last element in an array carModels[1] = "Chrysler"; // replace "Chevrolet"
We should mention that you can have (and even intermix) objects in arrays, functions in arrays, or even arrays in arrays:
myArray = [ 10, "Widget", [ 1, 2, 3 ], { object defn }, function defn ];
Although it is allowed, it is not recommended to use the "new Array" notation when defining an array:
var carModels = new Array("Ford", ...); // NOT RECOMMENDED
You can also use built-in JavaScript properties and methods on arrays, as follows in the next section.
Here are some built-in properties and methods that can be applied to arrays. Some of them (like slice and split) have already been discussed as applying to strings also. Brief descriptions are included as comments.
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; carModels.length; // = 3 // Typically properties can't be changed, but in this case they can ... carModels.length = 4; // this creates an empty fourth value carModels.length = 2; // this truncates the array to 2 values typeof(carModels); // = "object" (note that "of" is not an initial cap, for no obvious reason...) typeof carModels; // = "object" (and equally bizarrely you can use this alternate notation...) Array.isArray(carModels); // = true (this is the best way to test for an array) carModelsReverse = carModels.reverse(); // = [ "Dodge", "Chevrolet" ,"Ford" ] carModels.toString(); // = Ford,Chevrolet,Dodge (note the lack of blanks) carModels.join(", "); // = Ford, Chevrolet, Dodge (includes conversion to string) // See the next section for more information about the following SORT method carModels.sort(); // = Chevrolet, Dodge, Ford (an object, unless converted to string) carModels.sort().join(" and "); // = Chevrolet and Dodge and Ford (as a string) carModels.slice(1,3); // = "Chevrolet", "Dodge" // slices out a portion of the array creating a new array, starting at element 1, up to but not 3 carModels.splice(2,,"Jeep"); // = Dodge (the removed item); but carModels is now Ford,Chevrolet,Jeep // for splice, operand 1 = position for add/remove; operand 2 = number to remove (can be 0); // and any additions follow; so here, at position 2 ("Dodge"), delete 1 item and insert "Jeep" there cars = "Buick,Chrysler,Plymouth"; carsArray = cars.split(","); // = [ "Buick", "Chrysler", "Plymouth" ] (splits string into an array) // Note that for split, you must specify the separator character // However, if you specify "", every character becomes a member of the array var carModelsForeign = [ "Fiat", "Ferrari", "Porsche" ]; var cars = carModels.concat(carModelsForeign); // = an array of six cars
Not discussed yet: .every, .some, .filter, .sort, .map methods.
We interrupt to remind you about alert below. alert pops a message to the screen. You may wish to substitute 'console.log' for 'alert' to place the output in the console debugging console. |
Sorting an array is simple in most cases, as shown above. However, sorting an array can be tricky, particularly if sorting numbers or if case insensitivity is desired. See this discussion of sort on w3schools and this discussion of case-insensitive sorts on StackOverflow. They both point out that sort takes an optional parameter which is a locally-supplied function to do the individual element comparisons.
arrayName.sort( [comparisonFunction] );
In the absence of a comparison function, the array elements are converted to strings, then sorted according to each character's Unicode code point value. If you are counting on leading numbers sorting correctly, they won't. Example:
myArray = [ "100 apples", "2 oranges" ]; alert(myArray.sort()); // = "100 apples,2 oranges" because 1 is less than 2 in the first column
To resolve this problem, you need to provide a function which effectively does the individual element-by-element comparison for the sort. Your function is automatically passed the two elements to be compared as parameters. Here is our revised call to the sort with our comparison function for an ascending sort:
myArray = [ "100 apples", "2 oranges" ]; alert(myArray.sort( function(a,b) {return a-b} )); // = "2 oranges,100 apples"
To make a descending sort, change the function to say return b-a.
For a case-insensitive sort, the solution is slightly more complex. Here is one solution:
arrayName.sort( function (a,b) {return a.toLowerCase().localeCompare(b.toLowerCase())} );
You might wish to do something with each and every value in an array. There are several options.
First we'll review the basic FOR statement as discussed in our Introduction to JavaScript, then we'll apply this basic form of FOR to arrays. Check the Introduction if you want to review the IF ELSE and ELSE options.
One method involves the for loop statement, whose basic syntax looks like this:
for (stmt1; stmt2; stmt3) { // code to be executed }
where:
So the idea is that you initialize the loop with stmt1, you increment some value with stmt3, and you continue execution of the loop if the condition in stmt 2 is satisfied. Example:
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; for (i=0; i<3; i++) { alert(i+". "+carModels[i]); } // which yields three alert boxes saying "0. Ford", "1. Chevrolet", and "2. Dodge"
So you read the above code like this: Initialize i to 0; execute the loop if i<3; and before you iterate, increment i by 1. The alert statement shows us the current value of i (initially 0 as defined by stmt1) and the current array element (initially the 0th or first element). Having issued the alert, stmt3 increments i and we iterate. i is now 1, so we repeat the process, and repeat it again with i = 2. However, when i reaches 3, the condition in stmt2 turns false, and we exit the loop.
If you want to handle everything within the loop, you could have written this or some variation:
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; i = 0; for (;;) { // reminder, 2 semicolons are required alert(i+". "+carModels[i]); i++; if (i>2) { break } }
The for...in statement (not to be confused with using JavaScript's in operator, which is completely different) will loop through all an array's values for you.
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; for (var key in carModels) { alert(key+". "+carModels[key]); }
One way to read this example is: loop through the array using the arbitrarily-named index key to go from 0 to the max value and do whatever follows on each value. In this example, note that if key were defined prior to the for statement, you would not use the var specification, which is otherwise required here. And by the way, this technique works for objects also, where you would not have to know the property names.
When applying the forEach method to an array, the expected operand is the name of a function that you have written. The function is then executed against every non-null element of the array and is automatically passed three parameters: the value of the current item ("item" below); the index of the current item ("index" below); and the array object the current element belongs to (not specified below). Only the first item is required to be specified.
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; function myFunction(item, index) { alert(index+" "+item); } carModels.forEach(myFunction); // shows "0 Ford" then "1 Chevrolet" then "2 Dodge"
push is a method which adds one or more values (pushes ...) to the end of an array and returns the new length, and pop is a method which removes (pops off...) the last element of an array and returns the value removed.
var carModels = [ "Ford", "Chevrolet", "Dodge" ]; // length = 3 carModels.push("Chrysler", "Tesla"); // length now = 5 lastOne = carModels.pop(); // lastOne = "Tesla" and length = 4
If instead you wish to access the beginning of the array, use shift and unshift (note that the s is not capitalized). The oddly-named unshift adds items to the beginning of an array and returns the new length, while shift removes an item from the beginning of an array and returns the value removed.
Parsing means splitting a line of text into component parts. It can be used to break down values in a database into individual JavaScript variables. By placing a string of values into an array, you can then assign variables to each element of the array. Here's an example from my own work using the split method.
// the current line of a database has been read into variable 'line' // a sample line looks like this: line = "dvds = 1105 /* 09/10/20 */" // we will now split this line up into an array of values using a blank as a separator let lineArray = line.split(" "); // returns 'variable = value /* date */' in our array 'lineArray' // index = 0 1 2 3 4 5 let variable = lineArray[0]; let value = lineArray[2]; let date = lineArray[4]; alert(variable+"="+value+" updated "+date); // = "dvds=1105 updated 09/10/20"
Note that the above technique will only work if the input lines have exactly one blank (or other character) between values, as the split is done after encountering a single occurence of the specified character. Consider this: a good way to create a database would be to separate all your values with a TAB character. You could then use this exact same technique by replacing the blank separator " " with "\t", the JavaScript notation for a tab.
Functions are described under Functions in our JavaScript Introduction document.
Should you wish to access a function's arguments individually, you can use the automatically-created arguments array (technically array-like, as not all array features are applicable...):
function addem (parm1,parm2) { alert("The first of "+arguments.length+" arguments is "+arguments[0]); } addem(5,4); // = "The first of 2 arguments is 5"
length is just about the only property allowed with arguments, but note that you can also alter an argument, as in arguments[1] = 11.
You can use arguments to access an unknown number of passed arguments, but a better method of doing this was introduced recently in all browsers except Internet Explorer (which is dead for updates, but beware!). It is called the rest parameter syntax (...) and is applied as a prefix to a variable name in the parameter field. The tricky part is that you may use the notation for all or some of the parameters, but only if you specify it as the last parameter. Thus either of the following is acceptable:
function fname (parm1, parm2, ...parms) function fname (...parms)
It is "tricky" in the sense that you need to remember when coding the function that not necessarily all parameters are identified in this manner, so the total number of parameters is not necessarily identical to arguments.length. You can find out how many are identified via the rest parameter by using parms.length in our example above.
So to process an unknown number of operands, here is an example:
function combine (...parms) { // by using the join method on the array, you can separate the arguments let output = parms.join(" "); // returns a string // parms.length would be the number of arguments passed return output; } let combination = combine("Fred", "R", "Brack"); alert(combination) // = "Fred R Brack"
If you want to be safe and cover any non-updated browser, you would do this, which I offer without further explanation! It is the same as above except for the bolded statement and the lack of any arguments defined.
function combine () { // the following stmt creates an array of all the passed arguments let input = Array.prototype.slice.call(arguments,0); // by using the join method on the array, you can separate the arguments let output = input.join(" "); // returns a string return output; } let combination = combine("Fred", "R", "Brack"); alert(combination) // = "Fred R Brack"
There is a nice example of how to use the above feature to create HTML lists on Mozilla's The arguments object page. It could easily be adapted to the rest parameter notation.
# # # # #
Fred