Yes. There are a number of ways to do it. Probably the cleanest looking would be to use the reduce() function:
const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };
const width = 3; // how many in each sub array.
const result = Object.keys(obj).map(key => obj[key]) // ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  .reduce((result, v) => {
    if (result[result.length - 1].length === width) {
      result.push([v]); // add new row
    } else {
      result[result.length - 1].push(v); // add to last row
    }
    return result;
  }, [[]]);
  
console.log(result);
 
 
This is a little more verbose then it needs to be, but more understandable.
First, I loop through and map() the object to a normal array.
Then, in the reduce() function, I start it with the first level of nested arrays. Then on each loop, I check the length of the last array in result. If it's full, I add a new array for the next row. Otherwise, I just add the value to the last row.
A more compact version would be:
const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };
const width = 3;
const result = Object.keys(obj).reduce((r, k) => 
  r.concat(
    r[r.length - 1].length === width 
      ? [[obj[k]]]
      : [r.pop().concat(obj[k])]
  ), [[]]);
console.log(result);
 
 
This example makes more use of .concat() so everything is technically on one line, though obviously it's a good bit harder to read and understand.