BoundLess Grid, grid with unknown and infinite dimension
An example of some alternatives that you could use, there may be things there that you prefer.



/*
  A grid which can have any bounds and be checked against.
  create: let grid = new BoundlessGrid();
  set: grid( 0,0, "start point" )
  get: let myVal = grid(0,0);
  delete y:  delete grid()[0][0];
  delete x: delete grid()[0];
  iterate: grid().forEach( (x,y,grid)=&gt; {... } );
*/
function* generateValues(object) {
  for (let value in object) {
    yield value;
  }
}

class BoundlessGrid {
  constructor() {
    this.grid = Object.create(null, {
      forEach: {
        value: callback =&gt; {
          for (let x of generateValues(this)) {
            for (let y of generateValues(Reflect.get(this, x))) {
              callback(x, y, this);
            }
          }
        },
        enumerable: false,
        writable: false
      }
    });
    this.deleteProperty = Reflect.deleteProperty.bind(null, this.grid);
    // return a function that abstracts the object into
    // something that has friendlier shorthand syntax
    return (x, y, val) =&gt; this.handler(x, y, val);
  }

  has(x) {
    return Reflect.has(this.grid, x);
  }

  set(x, y, val) {
    if (!this.has(x)) {
      const deleteProperty = this.deleteProperty;
      // automatically removes the x grid axis when
      // the last y point is deleted from that x
      Reflect.set(this.grid, x, Reflect.construct(Proxy, [Object.create(null), {
        deleteProperty(yAxis, y) {
          Reflect.deleteProperty(yAxis, y);
          if (Object.keys(yAxis).length === 0) {
            deleteProperty(x);
          }
        }
      }]));
    }
    Reflect.set(Reflect.get(this.grid, x), y, val);
  }

  get(x, y) {
    if (this.has(x)) {
      return Reflect.get(Reflect.get(this.grid, x), y);
    }
  }

  // Single function that delegates to others
  // by determining inputs
  handler(x, y, val) {
    if (x === undefined) {
      return this.grid;
    }
    return val === undefined ? this.get(x, y) : this.set(x, y, val);
  }
}

const grid = Reflect.construct(BoundlessGrid, []);
grid(5, 4, "test1");
grid(5, 3, "test2");
grid().forEach((x, y, g) =&gt; console.log(`loop: val of ${x} and ${y}`, g[x][y]));
delete grid()[5][4];
console.log("First deleted key at 5x 4y:", grid(5, 4));
console.log("Value at 5x 3y:", grid(5, 3));
console.log("array of 5x", grid()[5]);
delete grid()[5][3];
console.log("second deleted key exists?", grid(5, 3) !== undefined);
console.log("array 5x defined?", grid()[5]);