Friday, November 29, 2019

JavaScript Arrays

Introduction

A JavaScript array is an ordered collection of values: a value is called array's element, a value's numeric position is called the element's index.
JavaScript arrays indexes are 32-bits unsigned integer values: the index of the first element is 0, and the highest possible index is (232−2) ≡ 4,294,967,294.
Array values may be of any type and different types can be present in the same array.
JavaScript arrays are dynamic: they grow or shrink according to what is necessary.

A JavaScript array may be dense or sparse:

  • a dense array is an array whose element indexes are contiguous
  • a sparse array is an array whose element indexes are NOT contiguous: it have gaps/holes.

Every JavaScript arrays has a length property:

  • if the array is dense, the length property equals the number of elements and its value is one more than the highest index in the array.
  • if the array is sparse, the length property is greater than the number of elements.

JavaScript arrays are a specialized form of object where property names are integers

JavaScript typed arrays are array-like objects that offer a way to access binary data of byte arrays

  • typed arrays are used to work with memory buffers

1 Creating Arrays

How to create arrays:

  • array literal syntax
  • array literal syntax with spread notation and iterable objects
  • Array.of() and Array.from() factory methods
  • Array() constructor
1.1 Creating arrays with literal notation

You can create an array with an array literal, which is simply a comma separated list of array elements within square brackets.
For example:

var empty = []; // An array with no elements
console.log(empty); // []
    
var powerOfTwo = [1, 2, 4, 8, 16, 32, 64, 128, 256]; // An array with 9 numeric elements
console.log(powerOfTwo); // [1, 2, 4, 8, 16, 32, 64, 128, 256]

var miscellaneous = [ 2.73, true, "string", ]; // 3 elements of various types + trailing comma
console.log(miscellaneous ); // [2.73, true, "string"]

// array literals can contain object literals or other array literals:

var actors = [ 
    [ 1, {firstName: 'Uma', lastName: 'Thurman'} ], 
    [ 2, {firstName: 'Michael', lastName: 'Douglas'} ] 
];
console.log(actors); // [ Array[2], Array[2] ]

// If you omit a value from an array literal, you have created a sparse array:

var count = ["one",,"three"]; // A sparse array with length 3.
console.log(count); // (3) ["one", empty, "three"]
    
var sparse = [,,]; // A sparse array with length 2.    
console.log(sparse); // (2) [empty × 2]
1.2 Creating arrays with array literal and spread notation

use an array literal with the spread notation to include the elements of a given array in an array literal

let array = [1, 2, 3];
let array2 = [5, 6, 7];
let literal = [0, ...array, 4, ...array2]; 
console.log(literal); // (8) [0, 1, 2, 3, 4, 5, 6, 7]   

the spread notation is a way to create a shallow copy of an array

// the spread notation is a way to create a shallow copy of an array
let array = [1, 2, 3];
let copy = [...array];
console.log(copy); // (3) [1, 2, 3]

the spread notation works not only on arrays but also on any iterable object

JavaScript iterable objects are objects that can be iterated over in a for/of loop

  • JS built-in types iterables by default are: String, Array, array-like objects (arguments, NodeList), TypedArray, Map and Set.
  • other JS built-in types, such as Object, are not iterable.

Example: converting iterable objects to arrays with spread notation

 // use the spread notation to convert a string to array
let digits = [..."0123456789"];
console.log(digits); // (10) ['0','1','2','3','4','5','6','7','8','9']

// convert an array to Set and then again to array, 
// this removes duplicate elements from the array:
let letters = [...'bye bye world'];
console.log(letters); // (13) ["b", "y", "e", " ", "b", "y", "e", " ", "w", "o", "r", "l", "d"]
let noDuplicates = [...new Set(letters)];
console.log(noDuplicates); // (9) ["b", "y", "e", " ", "w", "o", "r", "l", "d"]
1.3 Creating arrays with Array.of() function

The Array.of() factory function creates a new array, using the argument values as elements of the new array

new_array = Array.of(element0 [, element1 [, ... [, elementn]]])
let empty  = Array.of()             // [], empty array
let single = Array.of(10)           // [10], array with a single element
let array  = Array.of(1, 2, 3, 4)   // [1, 2, 3, 4], array with 4 elements    
1.4 Creating arrays with Array.from() function

The Array.from() factory function creates a new array, taking as arguments an array-like or iterable object.

new_array = Array.from(object, [function])

Array.from(iterable) is equivalent to the literal array syntax [...iterable]

let digits = [..."0123456789"];
console.log(digits); // (10) ['0','1','2','3','4','5','6','7','8','9']

digits = Array.from("0123456789");
console.log(digits); // (10) ['0','1','2','3','4','5','6','7','8','9']

Array.from(array) offers a way to make a shallow copy of an array

let copy = Array.from(array)

Array.from() function allows to build a true array from an array-like object.

Array-like objects

  • they can access properties using numerical index and length property.
  • they do not inherit from Array.prototype, so Arrays methods cannot be called on array-like objects.
  • in client-side JavaScript, HTML DOM objects are comprised of array-like objects.
function argumentsToArray() {
  arrayOfArgs = Array.from(arguments);
  return arrayOfArgs;
}
console.log(argumentsToArray(1, 2, 3)); // [ 1, 2, 3 ]

Array.from() function takes a function as second optional parameter.

  • if a function is passed as second argument value, then each element of the first array argument is passed to the function and the return value is stored in the array that is being built and returned.
  • the second optional function works as in the Array.prototype.map() method
1.5 Creating arrays with Array() constructor
You can create an array invoking the Array() constructor. You can invoke the Array() constructor in three different ways:
// with no arguments:
var empty = new Array(); // empty array, like []
console.log(empty); // []
 
// with a single numeric arguments that become the array length.
// This allocates an array with no elements and no indexes
var arr2 = new Array(10); // a sparse array of length 10
console.log(arr2); // [] 
    
// with two or more arguments that become array elements
var arr3 = new Array(5, 10, "third elem", "fourth elem");
console.log(arr3); // [5, 10, "third elem", "fourth elem"]

The Array constructor belongs to the older versions of JavaScript; with the introduction of the two factory functions there should be no reason to use the Array constructor anymore.

2 Reading and Writing Array Elements

You read and write array elements using the square brackets operator [ ]

array[expression]
where:
  • array is a reference to the array object
  • expression evaluate to a non-negative integer value
Example: writing array elements
var array = [];
var i = 0;
array[i] = "hello"; // write element with index 0
array[i+1] = "world"; // write element with index 1
console.log(array); // ["hello", "world"]
Example: reading array elements
var array2 = ["good bye","blue sky"];    
// reading elements with indexes 0 and 1
var string = array2[0] + ", " + array2[1];
console.log(string); // "good bye, blue sky"

Arrays are a specialized kind of object.

You can access object properties using the square brackets like you access array elements. Since array are objects, in accessing an array's elements, array indexes are converted to string and treated as property names. In fact, when dealing with objects every property name is implicitly converted to string.
var object = {
  1: "a property"
};
object[2] = "another property";
console.log(object); // Object {1: "a property", 2: "another property"}

What is arrays' special feature?

When you index an array using property names that are non-negative integers, less than 232, the array automatically updates the value of the length property.
var array = [];
array[0] = "hello"; // write element with index 0
array[1] = "world"; // write element with index 1
console.log(array.length) // 2

3 Array Length

JavaScript arrays have a length property, and this characteristic makes arrays different from ordinary objects.
If the array is dense, the length property equals the number of elements and its value is one more than the highest index in the array.
var array = []; // no elements
array.length; // 0

var array2 = [1, 2, 3, 4, 5]; // five elements
array2.length; // 5: the greatest index is 4

// access last element 
console.log(array2[length-1]); // 5, 

4 Adding and Deleting Array Elements

How to add elements
  • by assigning a value to a new index
  • the push() method adds elements to the end of an array
  • the unshift() method inserts a value at the beginning of an array, this shifts the existing values to elements with greater indexes.
Example: adding a value to a new index
a = [] // Start with an empty array.
a[0] = "zero"; // And add elements to it.
a[1] = "one";

Example: adding values with push() and unshift() methods

var arr = [0]; // an array with an element.

// add two values at the end
arr.push(1);
arr.push(2);
console.log(arr); // [0, 1, 2]

// add two more values at the beginning
arr.unshift(-1); 
arr.unshift(-2);    
console.log(arr); // [-2, -1, 0, 1, 2]
How to delete elements
  • the pop() method removes the last element
  • the shift() method removes the first element
  • the delete operator removes an element, but the array becomes sparse
  • setting the length property to an integer n smaller than its current value remove all the elements with index greater or equal than n

Example: deleting values with pop() and shift() methods

var array = [-2, -1, 0, 1, 2];
array.pop(); // remove the last
console.log(array); // [-2, -1, 0, 1]
array.shift(); // remove the first
console.log(array); // [-1, 0, 1]

6 Iterating Arrays

You can iterate arrays:

  • with the for/of loop
  • with the forEach() method
  • with the basic for loop
6.1 - The for/of loop

In ES6, you can iterate any iterable object with a for/of loop

  • the for/of loop employs the built-in array iterator, which return undefined for sparse arrays
let numbers = ["0","1","2","3","4", ,"6"];
let text = "";
for(let num of numbers) {
  text += num;
}
console.log(text); // 01234undefined6

// use the for/of loop with elements' index
let text = "";
for(let [index, num] of numbers.entries()) {
  if (index % 2 == 0) // even indexes
    text += num; 
}
console.log(text);  // 0246
6.2 - Iterating arrays with the Array.prototype.forEach() method
let numbers = ["0","1","2","3","4", ,"6"];
let text = '';
numbers.forEach(num => text += num );
console.log(text);  // 012346

The forEach() method vs the for/of loop

  • the forEach() method is aware of sparse array, whereas the for/of loop is not
  • the forEach() method has access to the array index, whereas in the for/of loop you have to use the Array.prototype.entries() method and the destructured assignment.
6.3 - Iterating arrays with the basic for loop
let numbers = ["0","1","2","3","4", ,"6"];
let text='';
for(let i = 0; i < numbers.length; i++) {
  let number = numbers[i];
  text += number;
}
console.log(text); // => 01234undefined6

// using the for loop, looking up the length only once
let numbers = ["0","1","2","3","4", ,"6"];
let text='';
// Save the array length into a local variable
for(let i = 0, len = numbers.length; i < len; i++) {
  // the body remains the same
  let number = numbers[i];
  text += number;
}
console.log(text); // => 01234undefined6

// iterate sparse arrays with for loop, excluding gaps, undefined and null elements
let numbers = ["0","1","2","3","4", ,"6"];
let text='';
for(let i = 0, len = numbers.length; i < len; i++) {
  // skip gaps and undefined elements
  if (numbers[i] === undefined) continue;
  let number = numbers[i];
  text += number;
}
console.log(text); // => 012346
// note: change the comparison operator into == to also skip null elements. 

// iterate arrays with a for loop and the Object.keys() static function
let numbers = ["0","1","2","3","4", ,"6"];
let keys = Object.keys(numbers);
let values = []; 
for(var i = 0; i < keys.length; i++) {
  let key = keys[i];
  values.push(numbers[key]);
}
console.log(values); // ["0", "1", "2", "3", "4", "6"]

No comments:

Post a Comment