- An array is a special kind of object.
- The square brackets used to access a property arr[0] actually come from the object syntax.
- Numbers are used as keys.
- Arrays have their own implementation of
toString
method that returns a comma-separated list of elements.
- Arrays do not have
Symbol.toPrimitive
, neither a viable valueOf
, they implement only toString
conversion.
- They extend objects providing special methods to work with ordered collections of data and also the
length
property.
- Array is an object and thus behaves like an object.
- So typeof does not help to distinguish a plain object from an array.
- But arrays are used so often that there’s a special method for that:
Array.isArray(value)
.
- It returns true if the value is an array, and false otherwise.
alert(Array.isArray({})); // false
alert(Array.isArray([])); // true
- The following actions are possible, because arrays are objects at their base.
- We can add any properties to them.
- But the engine will see that we’re working with the array as with a regular object.
- Array-specific optimizations are not suited for such cases and will be turned off, their benefits disappear.
let fruits = []; // make an array
fruits[99999] = 5; // assign a property with the index far greater than its length
fruits.age = 25; // create a property with an arbitrary name
- The
length
property automatically updates when we modify the array.
- To be precise, it is actually not the count of values in the array, but the greatest numeric index plus one.
- Another interesting thing about the length property is that it’s writable.
- If we increase it manually, nothing interesting happens.
- If we decrease it, the array is truncated.
- So, the simplest way to clear the array is:
arr.length = 0;
let fruits = ["Apple", "Orange", "Plum"];
fruits[2] = 'Pear'; // now ["Apple", "Orange", "Pear"]
for (let i = 0; i < arr.length; i++) {
alert( arr[i] );
}
for (let fruit of fruits) {
alert( fruit );
}
// An array can store elements of any type.
let arr = [
'Apple',
{ name: 'John' },
true,
function() {
alert('hello');
}
];
arr[3](); // hello
// Although for..in is possible, it is considered as a bad idea:
// It iterates over all properties not just array elements.
// The for..in loop is optimized for generic objects, not arrays and thus is 10-100 times slower.
push
, pop
, shift
, unshift
- Methods push/pop run fast, while shift/unshift are slow.
const fruits = ["Apple", "Orange", "Pear"];
const pear = fruits.pop(); // remove "Pear"
// fruits: Apple, Orange
fruits.push("Pear"); // The call fruits.push(...) is equal to fruits[fruits.length] = ...
// fruits: Apple, Orange, Pear
// shift Extracts the first element of the array and returns it:
const firstElement = fruits.shift(); // remove Apple and alert it
// unshift Add the element to the beginning of the array:
fruits.unshift('Apple');
// fruits: Apple, Orange, Pear
// Methods push and unshift can add multiple elements at once.
fruits.push("Orange", "Peach");
fruits.unshift("Pineapple", "Lemon");
array.forEach()
let myList = ["Bilbo", "Gandalf", "Nazgul"];
myList.forEach((item, index, array) => {
console.log(`${item} is at index ${index} in ${array}`);
});
myList.forEach(alert);
indexOf
, lastIndexOf
& includes
let arr = [1, 0, false];
alert(arr.indexOf(0)); // 1
alert(arr.indexOf(false)); // 2
alert(arr.indexOf(null)); // -1
alert(arr.includes(1)); // true
- If we want to check for inclusion, and don’t want to know the exact index, then arr.includes is preferred.
- Also, a very minor difference of includes is that it correctly handles NaN, unlike indexOf/lastIndexOf.
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (should be 0, but === equality doesn't work for NaN)
alert( arr.includes(NaN) );// true (correct)
find
and findIndex
- The
find()
method returns the value of the first element in the array that satisfies the provided testing function.
- Otherwise undefined is returned.