Arrays

An array is an ordered set of values. You can refer to the array elements with a name and index. These are the three ways to create arrays in JavaScript:

var arr = new Array(1,2,3);
var arr = Array(1,2,3);
var arr = [1,2,3];

When these values are specified, the array is initialized with them as the array's elements. An array's length property is equal to the number of arguments. The bracket syntax is called an array literal. It's a shorter and preferred way to initialize arrays.

You have to use the array literal syntax if you want to initialize an array with a single element and the element happens to be a number. If you pass a single number value to the Array() constructor or function, JavaScript considers this parameter as the length of the array, not as a single element:

var arr = [10];
var arr = Array(10); // Creates an array with no element, but with arr.length set to 10
// The above code is equivalent to
var arr = [];
arr.length = 10;

JavaScript does not have an explicit array data type. However, you can use the predefined Array object and its methods to work with arrays in your applications. The Array object has methods to manipulate arrays in various ways, such as joining, reversing, and sorting them. It has a property to determine the array length and other properties for use with regular expressions.

You can populate an array by assigning values to its elements:

var days = [];
days[0] = "Sunday";
days[1] = "Monday";

You can also populate an array when you create it:

var arr_generic = new Array("A String", myCustomValue, 3.14);
var fruits = ["Mango", "Apple", "Orange"]

In most languages, the elements of an array are all required to be of the same type. JavaScript allows an array to contain any type of values:

var arr = [
  'string', 42.0, true, false, null, undefined,
  ['sub', 'array'], {object: true}, NaN
]; 

You can refer to elements of an Array using the element's index number. For example, suppose you define the following array:

var days = ["Sunday", "Monday", "Tuesday"]

You then refer to the first element of the array as colors[0] and the second element of the array as colors[1]. The index of the elements starts with 0.

JavaScript internally stores array elements as standard object properties, using the array index as the property name. The length property is different. The length property always returns the index of the last element plus one. As we discussed, JavaScript array indexes are 0-based: they start at 0, not 1. This means that the length property will be one more than the highest index stored in the array:

var colors = [];
colors[30] = ['Green'];
console.log(colors.length); // 31

You can also assign to the length property. Writing a value that is shorter than the number of stored items truncates the array; writing 0 empties it entirely:

var colors = ['Red', 'Blue', 'Yellow'];
console.log(colors.length); // 3
colors.length = 2;
console.log(colors); // ["Red","Blue"] - Yellow has been removed
colors.length = 0;
console.log(colors); // [] the colors array is empty
colors.length = 3;
console.log(colors); // [undefined, undefined, undefined]

If you query a non-existent array index, you get undefined.

A common operation is to iterate over the values of an array, processing each one in some way. The simplest way to do this is as follows:

var colors = ['red', 'green', 'blue']; 
for (var i = 0; i < colors.length; i++) { 
  console.log(colors[i]); 
}

The forEach() method provides another way of iterating over an array:

var colors = ['red', 'green', 'blue'];
colors.forEach(function(color) {
  console.log(color);
});

The function passed to forEach() is executed once for every item in the array, with the array item passed as the argument to the function. Unassigned values are not iterated in a forEach() loop.

The Array object has a bunch of useful methods. These methods allow the manipulation of the data stored in the array.

The concat() method joins two arrays and returns a new array:

var myArray = new Array("33", "44", "55");
myArray = myArray.concat("3", "2", "1"); 
console.log(myArray);
// ["33", "44", "55", "3", "2", "1"]

The join() method joins all the elements of an array into a string. This can be useful while processing a list. The default delimiter is a comma (,):

var myArray = new Array('Red','Blue','Yellow');
var list = myArray.join(" ~ "); 
console.log(list);
//"Red ~ Blue ~ Yellow"

The pop() method removes the last element from an array and returns that element. This is analogous to the pop() method of a stack:

var myArray = new Array("1", "2", "3");
var last = myArray.pop(); 
// myArray = ["1", "2"], last = "3"

The push() method adds one or more elements to the end of an array and returns the resulting length of the array:

var myArray = new Array("1", "2");
myArray.push("3"); 
// myArray = ["1", "2", "3"]

The shift() method removes the first element from an array and returns that element:

var myArray = new Array ("1", "2", "3");
var first = myArray.shift(); 
// myArray = ["2", "3"], first = "1"

The unshift() method adds one or more elements to the front of an array and returns the new length of the array:

var myArray = new Array ("1", "2", "3");
myArray.unshift("4", "5"); 
// myArray = ["4", "5", "1", "2", "3"]

The reverse() method reverses or transposes the elements of an array—the first array element becomes the last and the last becomes the first:

var myArray = new Array ("1", "2", "3");
myArray.reverse(); 
// transposes the array so that myArray = [ "3", "2", "1" ]

The sort() method sorts the elements of an array:

var myArray = new Array("A", "C", "B");
myArray.sort(); 
// sorts the array so that myArray = [ "A","B","c" ]

The sort() method can optionally take a callback function to define how the elements are compared. The function compares two values and returns one of three values. Let us study the following functions:

  • indexOf(searchElement[, fromIndex]): This searches the array for searchElement and returns the index of the first match:
    var a = ['a', 'b', 'a', 'b', 'a','c','a'];
    console.log(a.indexOf('b')); // 1
    // Now try again, starting from after the last match
    console.log(a.indexOf('b', 2)); // 3
    console.log(a.indexOf('1')); // -1, 'q' is not found
  • lastIndexOf(searchElement[, fromIndex]): This works like indexOf(), but only searches backwards:
    var a = ['a', 'b', 'c', 'd', 'a', 'b'];
    console.log(a.lastIndexOf('b')); //  5
    // Now try again, starting from before the last match
    console.log(a.lastIndexOf('b', 4)); //  1
    console.log(a.lastIndexOf('z')); //  -1

Now that we have covered JavaScript arrays in depth, let me introduce you to a fantastic library called Underscore.js (http://underscorejs.org/). Underscore.js provides a bunch of exceptionally useful functional programming helpers to make your code even more clear and functional.

We will assume that you are familiar with Node.js; in this case, install Underscore.js via npm:

npm install underscore

As we are installing Underscore as a Node module, we will test all the examples by typing them in a .js file and running the file on Node.js. You can install Underscore using Bower also.

Like jQuery's $ module, Underscore comes with a _ module defined. You will call all functions using this module reference.

Type the following code in a text file and name it test_.js:

var _ = require('underscore');
function print(n){
  console.log(n);
}
_.each([1, 2, 3], print);
//prints 1 2 3

This can be written as follows, without using each() function from underscore library:

var myArray = [1,2,3];
var arrayLength = myArray.length;
for (var i = 0; i < arrayLength; i++) {
  console.log(myArray[i]);
}

What you see here is a powerful functional construct that makes the code much more elegant and concise. You can clearly see that the traditional approach is verbose. Many languages such as Java suffer from this verbosity. They are slowly embracing functional paradigms. As JavaScript programmers, it is important for us to incorporate these ideas into our code as much as possible.

The each() function we saw in the preceding example iterates over a list of elements, yielding each to an iteratee function in turn. Each invocation of iteratee is called with three arguments (element, index, and list). In the preceding example, the each() function iterates over the array [1,2,3], and for each element in the array, the print function is called with the array element as the parameter. This is a convenient alternative to the traditional looping mechanism to access all the elements in an array.

The range() function creates lists of integers. The start value, if omitted, defaults to 0 and step defaults to 1. If you'd like a negative range, use a negative step:

var _ = require('underscore');
console.log(_.range(10));
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
console.log(_.range(1, 11));
//[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(_.range(0, 30, 5));
//[ 0, 5, 10, 15, 20, 25 ]
console.log(_.range(0, -10, -1));
//[ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 ]
console.log(_.range(0));
//[]

By default, range() populates the array with integers, but with a little trick, you can populate other data types also:

console.log(_.range(3).map(function () { return 'a' }) );
[ 'a', 'a', 'a' ]

This is a fast and convenient way to create and initialize an array with values. We frequently do this by traditional loops.

The map() function produces a new array of values by mapping each value in the list through a transformation function. Consider the following example:

var _ = require('underscore');
console.log(_.map([1, 2, 3], function(num){ return num * 3; }));
//[3,6,9]

The reduce() function reduces a list of values to a single value. The initial state is passed by the iteratee function and each successive step is returned by the iteratee. The following example shows the usage:

var _ = require('underscore');
var sum = _.reduce([1, 2, 3], function(memo, num){console.log(memo,num);return memo + num; }, 0);
console.log(sum);

In this example, the line, console.log(memo,num);, is just to make the idea clear. The output will be as follows:

0 1
1 2
3 3
6

The final output is a sum of 1+2+3=6. As you can see, two values are passed to the iteratee function. On the first iteration, we call the iteratee function with two values (0,1)—the value of the memo is defaulted in the call to the reduce() function and 1 is the first element of the list. In the function, we sum memo and num and return the intermediate sum, which will be used by the iterate() function as a memo parameter—eventually, the memo will have the accumulated sum. This concept is important to understand how the intermediate states are used to calculate eventual results.

The filter() function iterates through the entire list and returns an array of all the elements that pass the condition. Take a look at the following example:

var _ = require('underscore');
var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
console.log(evens);

The filter() function's iteratee function should return a truth value. The resulting evens array contains all the elements that satisfy the truth test.

The opposite of the filter() function is reject(). As the name suggests, it iterates through the list and ignores elements that satisfy the truth test:

var _ = require('underscore');
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
console.log(odds);
//[ 1, 3, 5 ]

We are using the same code as the previous example but using the reject() method instead of filter()—the result is exactly the opposite.

The contains() function is a useful little function that returns true if the value is present in the list; otherwise, returns false:

var _ = require('underscore');
console.log(_.contains([1, 2, 3], 3));
//true

One very useful function that I have grown fond of is invoke(). It calls a specific function on each element in the list. I can't tell you how many times I have used it since I stumbled upon it. Let us study the following example:

var _ = require('underscore');
console.log(_.invoke([[5, 1, 7], [3, 2, 1]], 'sort'));
//[ [ 1, 5, 7 ], [ 1, 2, 3 ] ]

In this example, the sort() method of the Array object is called for each element in the array. Note that this would fail:

var _ = require('underscore');
console.log(_.invoke(["new","old","cat"], 'sort'));
//[ undefined, undefined, undefined ]

This is because the sort method is not part of the String object. This, however, would work perfectly:

var _ = require('underscore');
console.log(_.invoke(["new","old","cat"], 'toUpperCase'));
//[ 'NEW', 'OLD', 'CAT' ]

This is because toUpperCase() is a String object method and all elements of the list are of the String type.

The uniq() function returns the array after removing all duplicates from the original one:

var _ = require('underscore');
var uniqArray = _.uniq([1,1,2,2,3]);
console.log(uniqArray);
//[1,2,3]

The partition() function splits the array into two; one whose elements satisfy the predicate and the other whose elements don't satisfy the predicate:

var _ = require('underscore');
function isOdd(n){
  return n%2==0;
}
console.log(_.partition([0, 1, 2, 3, 4, 5], isOdd));
//[ [ 0, 2, 4 ], [ 1, 3, 5 ] ]

The compact() function returns a copy of the array without all falsy values (false, null, 0, "", undefined, and NaN):

console.log(_.compact([0, 1, false, 2, '', 3]));

This snippet will remove all falsy values and return a new array with elements [1,2,3]—this is a helpful method to eliminate any value from a list that can cause runtime exceptions.

The without() function returns a copy of the array with all instances of the specific values removed:

var _ = require('underscore');
console.log(_.without([1,2,3,4,5,6,7,8,9,0,1,2,0,0,1,1],0,1,2));
//[ 3, 4, 5, 6, 7, 8, 9 ]
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset