Built-in-like Range in JavaScript
source link: https://dev.to/didof/built-in-like-range-in-javascript-4ckj
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Premise
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.
If you want to chat about nerdy things or just say hi, you can find me here:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK