Merge intersecting sub-arrays
I went full performance here, so no forEach and such. 
The idea is to use associative arrays and assume they cost O(1) for speed improvement. The steps of this algorithm:


For each number, store the index of the array it first appeared on. 
For repeated numbers, we have intersections. As resolving the intersection right now is not performant (we might have more intersections later), we will just mark the current array and the array that number first appeared on as neighbors.
After all this preprocessing, we are ready to solve the problem. What we are left with is a graph, where a node is an array inside input. For that node, we have stored its inmediate neighbors, which represent the other arrays that also had a common number with it.
Now we do a standard DFS to iterate over all direct and indirect neighbors of a node, where we keep adding the numbers of each of those nodes to the group we are making. 


The most expensive part of the algorithm is the sorting, which I´m not sure if you needed it. If you do not care about order, no need to sort them. The important part is that we only add each number to the result array once, and we process each number once, so except for the sorting, the complexity should be linear on the amount of numbers in input.



const input = [[1, 17], [3, 5], [5], [1, 3], [7], [2], [9, 8], [7, 2]];


function merge(input) {
    var numberGroup = {}
    var neighbors = new Array(input.length); // direct intersections
    var processed = new Array(input.length); // for the dfs
    
    for (var arrayIndex = 0; arrayIndex &lt; input.length; arrayIndex++) {
        var array = input[arrayIndex];
        neighbors[arrayIndex] = {}; // we don´t use [] because we don´t want to keep repeated neighbors
        processed[arrayIndex] = false;
        
        for (var i = 0; i &lt; array.length; i++) {
          var number = array[i];
          
          if (numberGroup.hasOwnProperty(number) == false) { // haven´t seen the number before
            numberGroup[number] = arrayIndex; // we mark its first apparition
          } else { // we connect the node with the one where this number appeared for the first time
            var neighbor = numberGroup[number]; 
            neighbors[arrayIndex][neighbor] = true;
            neighbors[neighbor][arrayIndex] = true;
          }
        }
    }
    
    //inline function, could be taken outside and pass input , processed and neighbors
    function makeGroup (index, group) { // dfs
      if (processed[index] == false) {
          processed[index] = true;
          
          for (var i = 0; i &lt; input[index].length; i++) {
            group[input[index][i]] = true; // we only care about key, so we put value true but could be false
          }
          
          for (var neighbor in neighbors[index]) makeGroup(neighbor, group)
          return true; // this makes a new group
      }
      return false; // this does not make a new group
    }
    
    var result = [];
    
    for (var i = 0; i &lt; input.length; i++) {
      var group = {};
      if(makeGroup(i, group)) {
        result.push(Object.keys(group).map(Number).sort((a, b) =&gt; a - b)); // pass the keys to an array and sort it
      }
    }
    
    return result;
}

console.log(merge(input));