Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Understanding a range function in JavaScript

So, I’m new to programming and I am having a bit of a trouble here. See, I wanted to write a small range function, like range(a,b) that would return an array with all numbers between a and b. So I googled and found this one:

const range = (min, max) => [...Array(max - min + 1).keys()].map(i => i + min);

This works perfectly fine, but I’m having a bit of trouble undertanding it, especially with the .keys() part. I thought .keys() was an Object function, that would return the key of a key/value pair of an object, but here it seems to me that it’s been used in an Array.

What am I understanding wrong here?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Appreciate the help!

>Solution :

Arrays also have a keys method and it’s central to this range function working as it should.

Here’s how that works:

  1. It creates an empty (sparse) array of the appropriate length (Array(max - min + 1).
  2. It gets an iterator for the keys of that array (.keys()). Keys in an arrays are the numbers 0 through the length of the array minus one.
  3. It spreads the elements from that iterator out into an array ([...]).
  4. It creates a new array by mapping each value in the array from #3, adding the min value to them (.map(i => i + min)).

Note that this creates multiple intermediate arrays and other objects. It’s unlikely to matter, but it can be done much more efficiently. For instance, with Array.from as shown by Nina, or even just a simple loop:

const range = (min, max) => {
    const result = [];
    for (let n = min; n < max; ++n) {
        result.push(n); // Or: `result[result.length] = n;` if you want to
                        // avoid the function call
    }
    return result;
};
const range = (min, max) => {
    const result = [];
    for (let n = min; n < max; ++n) {
        result.push(n);
    }
    return result;
};
console.log(range(5, 10));

That’s not nearly as cool-looking, though. 😀

But, I probably wouldn’t have range return an array at all unless I know for sure that’s the end product I’m always going to need. Instead, I’d have it return an iterator:

const range = function*(min, max) {
    for (let n = min; n < max; ++n) {
        yield n;
    }
};
        
for (const value of range(0, 10)) {
    console.log(value);
}
.as-console-wrapper {
    max-height: 100% !important;
}

You can always spread it out into an array (or use it with Array.from) if you need an array.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading