Built-in-like Range in JavaScript
Make it possible to generate any range of integers with built-in-like syntax.
Motivation? Honestly, none. Zero. Except for fun & study.
Basic functionality
You start by overriding the prototype of Number
with itself, but proxed.
Object.setPrototypeOf(
Number.prototype,
new Proxy(Number.prototype, {
// ...
})
);
In this way, any normal operations related to the prototype are not lost.
In the proxy you listen for access to any property via a getter. The third argument (receiver
) is the "object", in this case the number itself - you call it start
. It's already the right type, number.
The second argument corresponds to the name of the property, its typeof
is indeed string
.
Object.setPrototypeOf(
Number.prototype,
new Proxy(Number.prototype, {
get(_, _end, start) {
// _end -> '182' (typeof string)
// start -> 42 (typeof number)
}
})
)(42)[182];
It is sufficient to use parseInt
and, if it still isNaN
just throw an error/warning. Or just ignore it silently and fallback by returning start
.
let end = parseInt(_end);
if (isNaN(end)) {
// warning or error
// eventually, fallback
return start;
}
Assured that the typeof end
is also number
, you can proceed to generate the range.
return Array(end - start + 1)
.fill()
.map((_, i) => start + i);
Basic functionality is complete. Now the following code is perfectly valid.
(0)[5]; // [0, 1, 2, 3, 4, 5]
To make it not-end-inclusive, use
Array(end - start)
instead ofArray(end - start + 1)
.
Reverse range
To be able to do something like the following...
[5](0); // [5, 4, 3, 2, 1, 0]
Check if start > end
and if so swap both. Don't forget to sort the result in descending order.
The code is self-explanatory.
Object.setPrototypeOf(
Number.prototype,
new Proxy(Number.prototype, {
get(_, _end, start) {
// where (start)[_end]
let end = parseInt(_end);
if (isNaN(end)) {
// warning or error
// eventually, fallback
return start;
}
// sort behaviour - default ASC
let s = +1;
if (start > end) {
// swap
let tmp = start;
start = end;
end = tmp;
// sort behaviour - DESC
s = -1;
}
// generate range
return Array(end - start + 1)
.fill()
.map((_, i) => start + i)
.sort(() => s);
}
})
);
Result
42(
// 42
0
)[5](
// [0, 1, 2, 3, 4, 5]
0
)['foo'](
// #fallback -> 0
3
)[7](
// [3, 4, 5, 6, 7]
8
)[3]; // [8, 7, 6, 5, 4, 3]
Couldn't I have done the same thing with a range function? Yes, probably you should do it with a function.
Let this be a mental exercise and a way of making friends with the concept of prototype and proxy.
On This Page