These answers are great. I just wanted to give you an idea of how a more functional approach can solve the problem:
// auxiliary functions: const append = (x, xs) => xs.concat([x]); const prepend = (x, xs) => [x].concat(xs); // main function const range = (x, y, step, acc = [], op = append) => step && step < 0 ? range(y, x, -step, acc, prepend) : step && x <= y ? range(x + step, y, step, op(x, acc), op) // tail call : acc; console.log(range(1,5,1)); // [1,2,3,4,5] console.log(range(1,5,2)); // [1,3,5] console.log(range(1,5,6)); // [1] console.log(range(5,1,1)); // [] console.log(range(1,5,0)); // [] console.log(range(5,1,-1)); // [5,4,3,2,1] console.log(range(5,1,-2)); // [5,3,1] console.log(range(5,1,-6)); // [1] console.log(range(1,5,-1)); // []
Algorithm:
acc = [] and op = append default parameter values (accepted if omitted during function call)step && step < 0 , if step is zero, otherwise it is checked whether the step is negativerange(y, x, -step, acc, prepend) is called when step is negative and converts the range parameterization so that step can be positive (note that -step equivalent to -(-1) , which evaluates to 1 )range(x + step, y, step, op(x, acc), op) A recursive case, which means that the function calls itself (note that op can be either append or prepend depending on the initial sign of step , that x incremented by step and added / added to acc )acc base register that stops recursion and returns the accumulated array