BoundLess Grid, grid with unknown and infinite dimension The reason this was made was because of a combination of things. Firstly, it was made for me to get more acquainted with some ECMA2016 syntax. Secondly, this is a useful utility class when working with grids of undefined width and height, including negative points (I couldn't easily find some already made). Besides that, I also tried abstracting the class in a way, returning a function, I think would result in a convenient shorthand way of using the class. 

Any pointers would be appreciated. If there's something I could use / use better with the new ECMA2016 features, that'd be awesome to see!

I'm betting using get and set as function names in the class isn't such a great convention to follow, either.

For some reason, only parts of the code are pasted and reformatted weird online. Otherwise, it looks correct in Atom.

GitHub
JsFiddle demonstration

/*
    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 forEach(callback) {
    for (let x in this) {
        for (let y in this[x]) {
            callback(x, y, this);
        }
    }
};

class BoundlessGrid {
  constructor() {
    this.grid = { forEach: forEach };
    Object.defineProperty(this.grid, "forEach", { enumerable: "false" });
    // return a function that abstracts the object into
    // something that has friendlier shorthand syntax
    return (x, y, val) =&gt; {return this.handler(x, y, val)};
  }

  set(x, y, val) {
    if (!this.grid.hasOwnProperty(x)) {
      let self = this;
      // automatically removes the x grid axis when
      // the last y point is deleted from that x
      this.grid[x] = new Proxy({}, {
        deleteProperty(yAxis, y) {
          delete yAxis[y];
          if (Object.keys(yAxis).length == 0) { delete self.grid[x];}
        }
      });
    }
    this.grid[x][y] = val;
  }

  get(x, y) { if (this.grid.hasOwnProperty(x)) { return this.grid[x][y]; } }

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

module.exports = BoundlessGrid;
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]);