Overview
In JavaScript, an array represents a global object category utilized for data storage. It constitutes an ordered sequence or collection that can contain zero or more data types, which can be accessed through numerical indices starting from 0.
Arrays are advantageous as they enable the storage of numerous values within a single variable. This capability aids in structuring and streamlining our code, enhancing its readability and maintainability. An array is capable of containing various types of data, such as strings, numerical values, and objects.
Object in an Array
Similar to arrays found in various programming languages, the Array object in JavaScript provides a range of methods for frequently utilized array operations and allows for the storage of numerous items under one variable identifier.
An explanation:
JavaScript arrays are array objects with the following essential features rather than primitive types:
- JavaScript arrays support multiple data types and can be resized. Instead of this flexibility, typed arrays should be used.
- Because JavaScript arrays are not associative arrays, nonnegative integers (or their string equivalents) must be used to access the elements of the array rather than random strings as indexes.
- JavaScript arrays employ zero-based indexing, where the final element is found at the array's length minus one. The first element is at index 0, the second at index 1, and so on.
- JavaScript operations that copy arrays produce shallow copies. For any JavaScript object, the built-in copy operations are all standard and produce shallow copies rather than deep copies.
Indices for arrays
Array objects do not permit the use of arbitrary strings as indexes for their elements, unlike associative arrays; they must utilize nonnegative integers or their equivalent string representations. When attempting to access or assign values using non-integer identifiers, the array list itself is not directly affected. Instead, this action alters a variable associated with the property collection of the array object. It is important to note that the properties of the array object are separate from the elements contained within the array, and therefore, the functions for iterating through and modifying the array cannot be applied to these named properties.
Items contained in an array can be compared to the attributes of an object, akin to the way toString is considered an attribute, even though it functions as a method. Nevertheless, trying to access a particular item from an array can lead to a syntax error because of an improperly formatted property name.
arr.0; // a syntax error
Output
In JavaScript, when a property is prefixed with a numeral, it is necessary to access it via bracket notation rather than using dot notation. While it is possible to quote the array indices, for example, using years['2'] instead of years[2], this practice is usually unnecessary.
The JavaScript engine automatically transforms the number 2 in years[2] into a string through a process known as coercion. As a result, '2' and '02' would represent different indexes within the years object, which could create a situation where:
console.log(years["2"] !== years["02"]);
The sole legitimate index for the array is years['2']. While iterating through the array, the string property years['02'] will remain unreferenced.
Connection between size and numeric characteristics
- The length property of a JavaScript array is directly linked to its numerical properties.
- Some of the predefined array functions (such as join, slice, indexOf, etc.) consider the value of an array's length property during their execution.
- Alternative techniques (such as push, splice, etc.) also lead to changes in the length property of an array.
const fruits = [];
fruits.push("banana", "apple", "peach");
console.log(fruits.length); // 3
Output
When you set a value to a property of a JavaScript array that corresponds to a valid index but lies outside the current bounds of the array, the JavaScript engine will automatically modify the array's length property to accommodate this new index.
Array functions and uninitialized elements
When array methods interact with empty slots in sparse arrays, they exhibit varying behaviors. Standard methods (such as forEach) usually differentiate between indices that hold undefined values and those that are empty slots.
The methods concat, copyWithin, every, filter, flat, flatMap, forEach, indexOf, lastIndexOf, map, reduce, reduceRight, reverse, slice, some, sort, and splice provide specialized management for empty slots. Iteration methods like forEach do not iterate over empty slots at all. Conversely, methods such as concat and copyWithin maintain these open slots while copying, resulting in a sparse array.
Code:
const colors = ["red", "yellow", "blue"];
colors[5] = "purple";
colors.forEach((item, index) => {
console.log(`${index}: ${item}`);
});
Output
Contemporary methods, like keys, do not distinguish between vacant slots and regard them as if they contain undefined values. Strategies for merging null positions with unspecified elements encompass entries, fill, find, findIndex, findLast, findLastIndex, includes, join, keys, toLocaleString, toReversed, toSorted, toSpliced, values, and with.
Code:
const colors = ["red", "yellow", "blue"];
colors[5] = "purple";
const iterator = colors.keys();
for (const key of iterator) {
console.log(`${key}: ${colors[key]}`);
}
Output:
Methods of duplicating and changing data
Some methods produce a new array rather than modifying the existing one upon which they are executed. They achieve this by initiating with an empty array and subsequently appending elements to it.
The duplication procedure is superficial and does not go beyond the original array. The newly created array is populated with elements sourced from the original array(s) in this manner.
Objects: The newly created array holds a duplicate of the reference to the object. Both the original array and the modified array reference the same object. In simpler terms, if any changes are made to the referenced object, those changes will be reflected in both the original and the newly created arrays.
The newly created array is populated with primitive data types such as strings, numbers, and booleans, rather than with the objects String, Number, and Boolean.
Conversely, the array may undergo transformations through different methods that were called, resulting in changes to their return values, which could include a pointer to the initial array or the dimensions of the modified array.
By utilizing this.constructor[Symbol.species] to ascertain the appropriate constructor, the subsequent functions generate new arrays: concat, slice, splice, filter, flat, flatMap, and map, which collectively serve to produce the array of removed elements that is returned.
The Array base constructor consistently creates fresh arrays when employing functions such as toReversed, toSorted, toSpliced, and with.
The following table outlines the techniques that modify the original array, along with their respective non-mutating counterparts:
| Mutating method | Non-mutating alternative |
|---|---|
| copyWithin() | No one-method alternative |
| fill() | No one-method alternative |
| pop() | slice(0, -1) |
| push(v1, v2) | concat([v1, v2]) |
| reverse() | toReversed() |
| shift() | slice(1) |
| sort() | toSorted() |
| splice() | toSpliced() |
| unshift(v1, v2) | toSpliced(0, 0, v1, v2) |
Methods for generic arrays
Array methods do not directly interact with the internal data of the array object; rather, they operate in a generic manner. These methods are capable of accessing the elements of an array solely through indexed positions and the length property. Consequently, this means that these methods can also be utilized on objects that mimic the behavior of arrays.
const arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
console.log(Array.prototype.join.call(arrayLike, "+")); // 'x+y+z'
Array-like objects
An object that fails to throw an error during the length conversion process described earlier is classified as an array-like object. In practice, one would expect this type of object to possess indexed elements ranging from 0 to length - 1, along with a defined length property. (If any index is absent, it will behave akin to a sparse array.) When an array method is utilized on an array-like object, it disregards any integer index that is equal to or exceeds length - 1.
A variety of DOM objects, such as HTMLCollection and NodeList, exhibit characteristics similar to arrays. The arguments object also shares this array-like nature. Although these objects do not inherently possess array methods, you can still invoke array methods on them.
function a() {
console.log(Array.prototype.join.call(arguments, "+"));
}
a("x", "y"); // 'x+y'
Output
In summary
A fundamental and highly adaptable element of JavaScript programming is the array. This tutorial explored the process of creating arrays, their indexing methods, and several of the most common operations executed on them, such as inserting, removing, and modifying elements. Furthermore, we examined two methods for iterating over arrays, a commonly employed strategy for presenting data.