Как вам такое решение задачки?
Немного кривоватое на мой взгляд, я бы сделал такconst range = arr => arr
   .sort((a, b) => a - b)
   .reduce((agg, v) => {
      const currRange = agg[agg.length - 1]
      if (!currRange || v > currRange.last + 1) {
         agg.push({first: v, last: v})
      } else {
         currRange.last = v
      }
      return agg
   }, [])
   .map(v => v.first + (v.first !== v.last ? '-' + v.last : '')).join()
Можно воспользоваться тем фактом что в JavaScript в reduce()передаётся текущий индекс и сам массив, это позволяет упростить backreference. В итоге у меня получилось нечто подобное:/**
 * @param {Array} list
 * @return {string}
 */
const range = list => list
    .sort((a,b) => a - b)
    .reduce((r, v, i, a) => {
        if (i > 0 &&  v - a[i - 1] === 1) {
            let l = r.pop();
            l.push(v);
            r.push(l);
        } else {
            r.push([v]);
        }
        return r;
    }, [])
    .map(v => v.length > 1 ? `${v.shift()}-${v.pop()}` : v)
    .join(', ');
Кусок с pop/push можно ускорить за счёт усложнения обращения к массивам, но так код получается выразительнее.
Отдельное спасибо Дмитрий за .sort((a,b) => a - b) - не знал