Pagination algorithm in JS I needed a relatively simple pagination, as currently implemented on GoogleSearch (sans prev &amp; next buttons). Most code I've seen was overly complicated so I came up with something that's simpler. 

Any suggestions on how to further optimise this? 

function doPaging(currentPageInput) {

    let currentPage = currentPageInput, // input
        range       = 5,  // amount of links displayed 
        totalPages  = 20, // determined by amount of items, hardcoded for readability 
        start       = 1;  // default

    let paging = [];      // output variable

    // Don't use negative values, force start at 1
    if (currentPage &lt; (range / 2) + 1 ) {
        start = 1;

    // Don't go beyond the last page 
    } else if (currentPage &gt;= (totalPages - (range / 2) )) {
        start = Math.floor(totalPages - range + 1);

    } else {
        start = (currentPage - Math.floor(range / 2));
    }

    for (let i = start; i &lt;= ((start + range) - 1); i++) {
        if (i === currentPage) {
            paging.push(`[${i}]`); // add brackets to indicate current page 
        } else {
            paging.push(i.toString());
        }
    }
    return paging;
}


OUTPUT:

[ '[1]', '2', '3', '4', '5' ]
[ '1', '[2]', '3', '4', '5' ]
[ '1', '2', '[3]', '4', '5' ]
[ '2', '3', '[4]', '5', '6' ]
[ '3', '4', '[5]', '6', '7' ]
[ '4', '5', '[6]', '7', '8' ]
[ '5', '6', '[7]', '8', '9' ]
[ '6', '7', '[8]', '9', '10' ]
[ '7', '8', '[9]', '10', '11' ]
[ '8', '9', '[10]', '11', '12' ]
[ '9', '10', '[11]', '12', '13' ]
[ '10', '11', '[12]', '13', '14' ]
[ '11', '12', '[13]', '14', '15' ]
[ '12', '13', '[14]', '15', '16' ]
[ '13', '14', '[15]', '16', '17' ]
[ '14', '15', '[16]', '17', '18' ]
[ '15', '16', '[17]', '18', '19' ]
[ '16', '17', '[18]', '19', '20' ]
[ '16', '17', '18', '[19]', '20' ]
[ '16', '17', '18', '19', '[20]' ]
In addition to the remarks given by Blindman67, I'd like to suggest the following:

Passing options:

The first few lines of your function are some kind of configuration block:

let currentPage = currentPageInput, // input
    range       = 5,  // amount of links displayed 
    totalPages  = 20, // determined by amount of items, hardcoded for readability 
    start       = 1;  // default


Now, when the number of pages changes, you need to touch your code and modify the totalPages initialization.

So you will probably want to introduce function arguments with default values:

function doPaging(currentPageInput, start = 1, totalPages = 20, range = 5) {
  ...
}

// Example:
doPaging(3, 1, 4); // ["0", "1", "2", "[3]", "4"]


Unfortunately, if you e.g. desire to change just the number of total pages, this argument order still requires you to specify all arguments preceding the totalPages argument.

Therefore, you might want to consider using default parameters in combination with destructuring assignment:

function doPaging(currentPageInput, {start = 1, totalPages = 20, range = 5} = {}) {
  ...
}

// Example:
doPaging(3, {totalPages: 4}); // ["0", "1", "2", "[3]", "4"]


Separating logic and view:

Your current implementation returns an array of strings destined for immediate output. This comes with a few drawbacks:


If you want to change the markup of an active page index, you need to modify your code and replace the brackets [${i}] with something else.
If you want to output a usable pagination, e.g. a list of anchor tags, you need additional code to map each page index string to its URL. This would probably require you to map each index string back to a number first. 


So how about just returning the paging range as an array of numbers? Later on, within your HTML template, you can then print page == currentPage ? `[${page}]` : `${page}` or - in case you print HTML - simply select a different CSS class for the current page.

Handling corner cases:

In case you choose a range of 5, but the total number of pages is set to just 4, a call to doPaging(4) will return ["0", "1", "2", "3", "[4]"] including an undesired "0" at the beginning. A robust implementation should probably reduce the range according to the available total number of pages.

Fixing issues:

Since we now allow user defined start values, we need to fix issues arising from start values that are not 1 caused by the hard coded "force start at 1" within your code.

Putting it all together:

Choosing simpler and more consistent variable names as well as renaming the nondescript doPaging to getPagingRange, we get an easier to read and understand implementation.

Replacing the loop with Array.from yields more descriptive code.

Adding a single comment describing the function's behavior instead of many individual inline comments helps the reader to better understand the purpose and usage of the function.



/**
 * Return an integer range within [min, min + total) of given length centered
 * around the current page number.
 */
function getPagingRange(current, {min = 1, total = 20, length = 5} = {}) {
  if (length &gt; total) length = total;

  let start = current - Math.floor(length / 2);
  start = Math.max(start, min);
  start = Math.min(start, min + total - length);
 
  return Array.from({length: length}, (el, i) =&gt; start + i);
}

// Examples:
console.log(getPagingRange(20)); // [16, 17, 18, 19, 20]
console.log(getPagingRange(3, {total: 4, length: 3})); // [2, 3, 4]
console.log(getPagingRange(3, {min: 0, total: 4, length: 3})); // [1, 2, 3]