It's pretty common to want to create an array of a given length, and populate it depending on its index. At a really basic level, something like [1, 2, 3, 4, 5]
.
JS has a lot of nice high-level FP-style array methods, but creating something like [1, 2, 3, 4, 5]
is surprisingly clunky, or exposes you to some of the less idiomatic parts of JS.
Eg:
const result = Array(5).map((_, i) => i + 1);
The above doesn't work due to how methods treat 'empty' array entries. A common workaround is:
const result = Array(5).fill(0).map((_, i) => i + 1);
This still exposes you to the weirdness of 'empty' entries, iterates over the array twice, and leaves the reader with an irrelevant fill value to ignore.
const result = [...Array(5)].map((_, i) => i + 1);
This avoids the redundant fill value, but still exposes you to the weirdness of 'empty' entries and an extra iteration.
Alternatively:
const result = Array.from({ length: 5 }, (_, i) => i + 1);
The above avoids the redundant fill value, and the additional iteration, but it feels like a 'trick'. You need to create a value that will cause Array.from
to create an array of a given length, and treat each entry as non-empty.
This stuff is easy with a plain for-loop of course:
const result = [];
for (let i = 0; i < 5; i++) result[i] = i + 1;
β¦but that doesn't fit in with the high-level FP-style methods that already exist.
Should we have something to make this easier, such as:
const result = Array.create(5, (i) => i + 1);
Although all the examples in this post could be satisfied with some sort of range, I don't think the functionality should be limited to ranges. It should be useful in other cases, eg:
function createPoints(input) {
// input is an array of numbers like [x, y, x, y, x, y]
return Array.create(input.length / 2, (i) => ({
x: input[i * 2],
y: input[i * 2 + 1],
}));
}