JS Tip of the Day: Generating Ranges

Generating Ranges
Version: ES2015 (generators)
Level: Intermediate

Have you ever needed to run through a sequence of numbers, or to create a range of values between two numbers? If so, you may have used a for loop. They’re often well suited for this purpose.

for (let i = 0; i < 5; i++) {
    console.log(i); // 0 1 2 3 4
}

We can take this idea further and create a function specifically for creating a number sequence like this. If you’re familiar with Python, you may already be familiar with the built-in range() function it has which does this. We can recreate that same function for JavaScript with the help of generators.

The range() function takes anywhere from 1 to 3 arguments. It works much like a for loop having a starting value, counting up to but not including an ending value, and finally using an increment value to determine how to go between them. For the values not provided, defaults are supplied. Also, if only one argument is passed, it is considered the ending value with the starting value being 0. A simple generator function to accomplish this (not accounting for and argument validation and other fancy error handling etc.) would look something like:

function * range (startOrEnd, end = undefined, step = 1) {
    let start = startOrEnd;
    if (end === undefined) {
        end = startOrEnd;
        start = 0;
    }
    for (let i = start; i < end; i += step) {
        yield i;
    }
}

To use this in place of the for loop used earlier, a for...of is used instead, iterating through the values of the generator object created when range() is called.

for (let num of range(5)) {
    console.log(num); // 0 1 2 3 4
}

While you’re not exactly saving a lot in terms of code size here, this does become easier to read and your intentions of creating a range is more clear. More importantly, because range() uses a generator, it can be used anywhere iterables are accepted! For example, you can easily add a range of values into a new array or spread them into a function call.

let evens = [...range(2, 11, 2)];
console.log(evens); // [2, 4, 6, 8, 10]

let obviously = Math.min(...range(1, 1000));
console.log(obviously); // 1

More info: