1

Built-in-like Range in JavaScript

 2 years ago
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, {
    // ...
  })
)
Enter fullscreen modeExit fullscreen mode

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]
Enter fullscreen modeExit fullscreen mode

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
}
Enter fullscreen modeExit fullscreen mode

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)
Enter fullscreen modeExit fullscreen mode

Basic functionality is complete. Now the following code is perfectly valid.

(0)[5] // [0, 1, 2, 3, 4, 5]
Enter fullscreen modeExit fullscreen mode

To make it not-end-inclusive, use
Array(end - start) instead of Array(end - start + 1).


Reverse range

To be able to do something like the following...

[5](0) // [5, 4, 3, 2, 1, 0]
Enter fullscreen modeExit fullscreen mode

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)
    },
  })
)
Enter fullscreen modeExit fullscreen mode

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]
Enter fullscreen modeExit fullscreen mode

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:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK