There’s so much more to arrays than map()
, filter()
, find()
, and push()
.
But most devs are completely clueless about this — several powerful methods they’re missing out on.
Check these out:
1. copyWithin()
Array
copyWithin()
copies a part of an array to another position in the same array and returns it without increasing its length.
const array = [1, 2, 3, 4, 5];
// copyWithin(target, start, end)
// replace arr with start..end at target
// a. target -> 3 (index)
// b. start -> 1 (index)
// c. end -> 3 (index)
// start..end -> 2, 3
const result = array.copyWithin(3, 1, 3);
console.log(result); // [1, 2, 3, 2, 3]
end
parameter is optional:
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// "end" not specified so last array index used
// target -> 0 (index)
// start..end -> 6, 7, 8, 9, 10
const result = array.copyWithin(0, 5);
// [6, 7, 8, 9, 10, 6, 7, 8, 9, 10]
console.log(result);
const array = [1, 2, 3, 4, 5];
// Copy numbers 2, 3, 4, and 5 (cut off at index 4)
const result = array.copyWithin(3, 1, 6);
console.log(result); // [1, 2, 3, 2, 3]
2. at() and with()
at()
came first and with()
came a year after that in 2023.
They are the functional and immutable versions of single-element array modification and access.
const colors = ['pink', 'purple', 'red', 'yellow'];
console.log(colors.at(1)); // purple
console.log(colors.with(1, 'blue'));
// ['pink', 'blue', 'red', 'yellow']
// Original not modified
console.log(colors);
// ['pink', 'purple', 'red', 'yellow']
The cool thing about these new methods is how they let you get and change element values with negative indexing.
3. Array
reduceRight()
method
Works like reduce()
but the callback goes from right to left instead of left to right:
const letters = ['b', 'e', 'a', 'u', 't', 'y'];
const word = letters.reduce((word, letter) => word + letter, '');
console.log(word); // beauty
// Reducer iterations
// 1. ('', 'y') => '' + 'y' = 'y'
// 2. ('y', 't') => 'y' + 't' = 'yt';
// 3. ('yt', 'u') => 'ytu';
// ...
// n. ('ytuae', 'b') => 'ytuaeb';
const wordReversed = letters.reduceRight((word, letter) => word + letter, '');
console.log(wordReversed); // ytuaeb
Here’s another great scenario for reduceRight()
:
const thresholds = [
{ color: 'blue', threshold: 0.7 },
{ color: 'orange', threshold: 0.5 },
{ color: 'red', threshold: 0.2 },
];
const value = 0.9;
const threshold = thresholds.reduceRight((color, threshold) =>
threshold.threshold > value ? threshold.color : color
);
console.log(threshold.color); // red
4. Array findLast()
method
New in ES13: find array item starting from last element.
Great for cases where where searching from end position produces better performance than with find()
Example:
const memories = [
// 10 years of memories...
{ date: '2020-02-05', description: 'My first love' },
// ...
{ date: '2022-03-09', description: 'Our first baby' },
// ...
{ date: '2024-01-25', description: 'Our new house' },
];
const currentYear = new Date().getFullYear();
const query = 'unique';
const milestonesThisYear = events.find(
(event) =>
new Date(event.date).getFullYear() === currentYear &&
event.description.includes(query)
);
This works but as our target object is closer to the tail of the array, findLast()
should run faster:
const memories = [
// 10 years of memories...
{ date: '2020-02-05', description: 'My first love' },
// ...
{ date: '2022-03-09', description: 'Our first baby' },
// ...
{ date: '2024-01-25', description: 'Our new house' },
];
const currentYear = new Date().getFullYear();
const query = 'unique';
const milestonesThisYear = events.findLast(
(event) =>
new Date(event.date).getFullYear() === currentYear &&
event.description.includes(query)
);
Another use case for findLast()
is when we have to specifically search the array from the end to get the correct element.
For example, if we want to find the last even number in a list of numbers, find()
would produce a totally wrong result:
const nums = [7, 14, 3, 8, 10, 9];
// gives 14, instead of 10
const lastEven = nums.find((value) => value % 2 === 0);
console.log(lastEven); // 14
But findLast()
will start the search from the end and give us the correct item:
const nums = [7, 14, 3, 8, 10, 9];
const lastEven = nums.findLast((num) => num % 2 === 0);
console.log(lastEven); // 10
5. toSorted()
, toReversed()
, toSpliced()
ES2023 came fully packed with immutable versions of sort()
, reverse()
, and splice()
.
Okay maybe splice()
isn’t used as much as the others, but they all mutate the array in place.
const original = [5, 1, 3, 4, 2];
const reversed = original.reverse();
console.log(reversed); // [2, 4, 3, 1, 5] (same array)
console.log(original); // [2, 4, 3, 1, 5] (mutated)
const sorted = original.sort();
console.log(sorted); // [1, 2, 3, 4, 5] (same array)
console.log(original); // [1, 2, 3, 4, 5] (mutated)
const deleted = original.splice(1, 2, 7, 10);
console.log(deleted); // [2, 3] (deleted elements)
console.log(original); // [1, 7, 10, 4, 5] (mutated)
Immutability gives us predictable and safer code; debugging is much easier as we’re certain variables never change their value.
Arguments are exactly the same, with splice()
and toSpliced()
having to differ in their return value.
const original = [5, 1, 3, 4, 2];
const reversed = original.toReversed();
console.log(reversed); // [2, 4, 3, 1, 5] (copy)
console.log(original); // [5, 1, 3, 4, 2] (unchanged)
const sorted = original.toSorted();
console.log(sorted); // [1, 2, 3, 4, 5] (copy)
console.log(original); // [5, 1, 3, 4, 2] (unchanged)
const spliced = original.toSpliced(1, 2, 7, 10);
console.log(spliced); // [1, 7, 10, 4, 5] (copy)
console.log(original); // [5, 1, 3, 4, 2] (unchanged)
6. Array lastIndexOf()
method
The lastIndexOf()
method returns the last index where a particular element can be found in an array.
const colors = ['a', 'e', 'a', 'f', 'a', 'b'];
const index = colors.lastIndexOf('a');
console.log(index); // 4
We can pass a second argument to lastIndexOf()
to specify an index in the array where it should stop searching for the string after that index:
const colors = ['a', 'e', 'a', 'f', 'a', 'b'];
// Get last index of 'a' before index 3
const index1 = colors.lastIndexOf('a', 3);
console.log(index1); // 2
const index2 = colors.lastIndexOf('a', 0);
console.log(index2); // 0
const index3 = colors.lastIndexOf('f', 2);
console.log(index3); // -1
7. Array flatMap()
method
The flatMap()
method transforms an array using a given callback function and then flattens the transformed result by one level:
const arr = [1, 2, 3, 4];
const withDoubles = arr.flatMap((num) => [num, num * 2]);
console.log(withDoubles); // [1, 2, 2, 4, 3, 6, 4, 8]
Calling flatMap()
on the array does the same thing as calling map()
followed by a flat()
of depth 1, but it`s a bit more efficient than calling these two methods separately.
const arr = [1, 2, 3, 4];
// flat() uses a depth of 1 by default
const withDoubles = arr.map((num) => [num, num * 2]).flat();
console.log(withDoubles); // [1, 2, 2, 4, 3, 6, 4, 8]
Final thoughts
They are not that well-known (yet) but they have their unique uses and quite powerful.
Every Crazy Thing JavaScript Does
A captivating guide to the subtle caveats and lesser-known parts of JavaScript.