[JavaScript] Array
Arrays in JS are sparse array that is not continuously connected in memory.
Compared to a typical array, accessing the index is fast, and inserting/deleting is slow.
Neither JS arrays' length nor its elements' types are fixed.
Create Arrays
There are 4 ways to create arrays.
Array Literal
const arr1 = [1, 2, 3];
const arr2 = ["apple", 2, "carrot", 4];
Array Constructor
const arr = new Array(3); // [empty x 3]
const arr2 = new Array(1, 2, 3); // [1, 2, 3]
of() Method
const arr = Array.of(3); // [3]
const arr2 = Array.of(1, 2, 3); // [1, 2, 3]
from() Method
We can create an array using an array-like object through this method.
const arr = Array.from('test'); // ['t', 'e', 's', 't']
const arr2 = Array.from({ length: 3, 0: 1, 1: 2, 2: 3 }); // [1, 2, 3]
const arr3 = Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]
Properties of Arrays
length
let arr = [1, 2, 3];
console.log(`[${arr}]: ${arr.length}`);
// [1, 2, 3]: 3
arr.length = 7;
console.log(`[${arr}]: ${arr.length}`);
// [1, 2, 3, , , , ]: 7
arr.length = 2;
console.log(`[${arr}]: ${arr.length}`);
// [1, 2]: 2
The length property returns the number of the array's elements.
You can directly manipulate this property and the array will be changed.
Check Arrays
We can check whether it is an array using the isArray() method.
// true
Array.isArray([]);
Array.isArray(new Array());
Array.isArray([1, 2]);
// false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(1);
Array.isArray('array');
Array.isArray(true);
Array.isArray(false);
Array.isArray({ 0: 1, length: 1 });
We can also check whether it is an element of the arrays using indexOf() and includes() methods.
const fruits = ['apple', 'banana', 'cherry'];
if (fruits.indexOf('durian') === -1) {
console.log('Not Found');
}
if (fruits.includes('eggplant')) {
console.log('Found');
}
// Check from index 1
if (fruits.includes('cherry', 1)) {
console.log('Found');
}
indexOf() method returns an index if the argument is in the array, and returns -1 if not.
Access to Arrays
We can access elements of arrays through the [] operator with index.
It returns undefined if we try to access nonexistence elements.
const arr = [1, 2, 3, 4, 5];
arr[2]; // 3
arr[10]; // undefined
Find Elements
We can find elements of arrays through the indexOf() method with the value we want to find.
It returns the index of the element it finds.
As seen above, if not found, it returns -1.
const arr = [1, 2, 3, 4, 3, 2, 1];
arr.indexOf(2); // 1
arr.indexOf(5); // -1
// find value 2 from index 3
arr.indexOf(2, 3); // 5
The second argument means from where to find the value if it exists.
lastIndexOf() method are reverse direction of indexOf() method.
const arr = [1, 2, 3, 4, 3, 2, 1];
arr.lastIndexOf(2); // 5
arr.lastIndexOf(5); // -1
// find value 2 from index 3
arr.lastIndexOf(2, 3); // 1
Add Elements
push() Method
This method appends elements to the last of the array.
It has a side effect that changes original arrays.
const arr = [];
arr.push(1); // returns: 1
// arr: [1]
arr.push(2, 3); // returns: 3
// arr: [1, 2, 3]
arr.push([4, 5]); // returns: 4 (length)
// arr: [1, 2, 3, [4, 5]]
In addition, this method does not have a good performance, so if there is only one element to add, the following way is recommended.
const arr = [];
arr[arr.length] = 1; // returns: 1
// arr: [1]
unshift() Method
This method adds elements to the start of the array.
And, this method also has a side effect and is slower than the push() method.
const arr = [];
arr.unshift(1); // returns: 1 (length)
// arr: [1]
arr.unshift(2, 3); // returns: 3 (length)
// arr: [2, 3, 1]
arr.unshift([4, 5]); // returns: 4 (length)
// arr: [[4, 5], 2, 3, 1]
concat() Method
This method has no side effects and can replace push() and unshift() methods.
const arr = [];
const arr2 = arr.concat(1);
// arr2: [1]
const arr3 = arr2.concat(2, 3);
// arr3: [1, 2, 3]
const arr4 = arr3.concat([4, 5]);
// arr4: [1, 2, 3, 4, 5]
const arr5 = [6, 7].concat(arr4);
// arr5: [6, 7, 1, 2, 3, 4, 5]
Spread Operator
This method has no side effects and is easy to understand.
Therefore, it is recommended.
In addition, it can cover all the above methods.
const arr = [];
const arr2 = [...arr, 1];
// arr2: [1]
const arr3 = [...arr2, [2, 3]];
// arr3: [1, [2, 3]]
const arr4 = [-2, -1, ...arr3];
// arr4: [-2, -1, 1, [2, 3]]
const arr5 = [-3, ...arr4, 4];
// arr5: [-3, -2, -1, 1, [2, 3], 4]
Delete Elements
pop() Method
This method returns the last element of the array and deletes it.
It has a side effect.
const arr = [1, 2, 3, 4, 5];
arr.pop(); // 5
// arr: [1, 2, 3, 4]
We can delete elements in the middle of the element.
It only deletes the element's value, so be careful when using this way.
const arr = [1, 2, 3, 4, 5];
delete arr[2]; // true
// arr: [1, 2, empty, 4, 5]
shift() Method
This method returns the first element of the array and deletes it.
It has a side effect.
const arr = [1, 2, 3, 4, 5];
arr.shift(); // 1
// arr: [2, 3, 4, 5]
Splice and Slice
The splice() method adds or deletes a specific number of elements from a particular location.
It has a side effect.
const arr = [1, 2, 3, 4, 5];
// Delete 2 elements from index 1
arr.splice(1, 2); // [2, 3]
// arr: [1, 4, 5]
// Delete 2 elements from index 1 and insert 6 into there
arr.splice(1, 2, 6); // [4, 5]
// arr: [1, 6]
// Delete nothing and insert [2, 3] into index 1
arr.splice(1, 0, [2, 3]); // []
// arr: [1, [2, 3], 6]
// Delete all elements from index 1
arr.splice(1); // [[2, 3], 6]
// arr: [1]
The slice() method creates a new array with a specific number of elements from a particular location.
Therefore, it has no side effects.
const arr = [1, 2, 3, 4, 5];
// Copy from index 1
const arr2 = arr.slice(1);
// arr2: [2, 3, 4, 5]
// Copy index 0 ~ index 3 (not included)
const arr3 = arr2.slice(0, 3);
// arr3: [2, 3, 4]
// Copy 2 elements from the end
const arr4 = arr3.slice(-2);
// arr4: [3, 4]
// Shallow copy
const arr5 = arr4.slice();
// arr5: [3, 4]
Array Methods
join() Method
This method converts all elements to strings and joins them with a separator.
The default separator is a comma.
It has no side effects.
const arr = [1, 2, 3, 4, 5];
arr.join(); // 1,2,3,4,5
arr.join('-'); // 1-2-3-4-5
arr.join(''); // 12345
// arr: [1, 2, 3, 4, 5]
fill() Method
This method fills the elements' values to the designated value.
It has a side effect.
const arr = [1, 2, 3, 4, 5];
arr.fill(0);
// arr: [0, 0, 0, 0, 0]
// Fill 7 from index 2
arr.fill(7, 2);
// arr: [0, 0, 7, 7, 7]
// Fill 5 from index 1 ~ index 3 (not included)
arr.fill(5, 1, 3);
// arr: [0, 5, 5, 7, 7]
flat() Method
This method flattens the array recursively by the argument.
The default depth is 1.
It has no side effects.
const arr = [1, [2, [3, [4, [5]]]]];
const arr2 = arr.flat();
// arr2:[1, 2, [3, [4, [5]]]]
const arr3 = arr.flat(2);
// arr3: [1, 2, 3, [4, [5]]]
const arr4 = arr.flat(Infinity);
// arr4: [1, 2, 3, 4, 5]
reverse() Method
This method reverses the array.
It has a side effect.
const arr = [1, 2, 3, 4, 5];
arr.reverse(); // [5, 4, 3, 2, 1]
// arr: [5, 4, 3, 2, 1]
High-Order Methods
High-Order methods are methods that can be input by function.
forEach() Method
This method traverses the array.
const arr = [1, 2, 3];
const pow = [];
arr.forEach(
elem => pow[pow.length] = (elem ** 2)
);
// pow: [ 1, 4, 9 ]
find() Method
This method returns the value of the first element found.
const users = [
{ id: 1, name: "HoYa" },
{ id: 2, name: "Kim" },
{ id: 3, name: "Park" },
{ id: 1, name: "Lee" },
];
users.find(elem => elem.id === 1);
// { id: 1, name: 'HoYa' }
findIndex() Method
This method returns the index of the first element found.
const users = [
{ id: 1, name: "HoYa" },
{ id: 2, name: "Kim" },
{ id: 3, name: "Park" },
{ id: 1, name: "Lee" },
];
console.log(users.findIndex(elem => elem.name === 'Park'));
// 2
function getByKey(key, value) {
return elem => elem[key] === value;
}
console.log(users.findIndex(getByKey('name', 'HoYa')));
// 0
sort() Method
This method has a side effect.
If the return value of the comparator function is less than 0, it sorts using the first argument, if it is 0, it doesn't sort, and if it is greater than 0, it sorts using the second argument.
const arr = [3, 1, 2];
// ascending
arr.sort();
// arr: [ 1, 2, 3 ]
// descending
arr.sort((x, y) => y - x);
// arr: [ 3, 2, 1 ]
map() Method
This method creates a new array populated with the results of the provided function on every element in the array.
const arr = [1, 2, 3];
const arr2 = arr.map(elem => elem * 2);
// arr2: [ 2, 4, 6 ]
filter() Method
This method creates a new array with all elements that pass the test implemented by the provided function.
const arr = [1, 2, 3, 4, 5];
const arr2 = arr.filter(elem => elem % 2);
// arr2: [ 1, 3, 5 ]
reduce() Method
This method executes a provided reducer function on each element of the array, resulting in a single output value.
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduce((acc, val) => acc + val, 0);
// 15 <- 0 + 1 + 2 + 3 + 4 + 5
const average = arr.reduce(
(acc, cur, idx, { length }) =>
idx === length - 1 ? (acc + cur) / length : acc + cur,
0
);
// 3
const fruits = ["apple", "banana", "cherry", "banana", "apple"];
const counts = fruits.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
// { apple: 2, banana: 2, cherry: 1 }
reduceRight() Method
Unlike reduce() method, this method applies from the last element.
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduceRight((acc, val) => acc - val, 0);
// -15 <- 0 - 5 - 4 - 3 - 2 - 1
some() Method
This method returns true if at least one element of the array is satisfied with the given testing function, otherwise returns false.
const arr = [1, 2, 3, 4, 5];
arr.some(elem => elem > 4); // true
every() Method
This method returns true if all elements of the array are satisfied with the given testing function, otherwise returns false.
const arr = [1, 2, 3, 4, 5];
arr.every(elem => elem < 7); // true
flatMap() Method
This method is added in ES10.
It has the effect of executing the map() method and flat() method in order.
But, it only flattens by 1 depth.
const arr = ['hello', 'world'];
const arr2 = arr.flatMap(x => x.split(''));
// arr2: [ 'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd' ]