I'm implementing a JavaScript interpreter, and I can't figure out the details of binding functions to objects in JavaScript.
A rudimentary example:
const o = {
  x: 1,
  getX: function() {
    return this.x;
  }
};
o.getX(); // returns 1
The tricky part is what happens when you assign getX to a variable:
let gX = o.getX;
gX(); // returns undefined
My question is: how does the runtime know that o.getX() gets bound to o, but gX() should be unbound? I would assume gX and o.getX are pointing to the exact same function!
I first thought that maybe the presence of the . is what makes the difference. So, in the grammar, there's a production like <method-call> ::= <expr> '.' ID '(' <expr>* ')', and this expression is treated differently (the result of evaluating the first <expr> is bound to the function found under ID) than a "regular" call (without a .).
But the following expression seems to disprove this theory, because (o.getX)() also returns 1. However, in some magical way, (gX = o.getX)() returns undefined, even though it's clear to me the assignment expression returns its right-hand size, so o.getX in this case!
Is there a simple explanation of how these semantics are implemented? I can't figure out a way that my runtime is supposed to differentiate that o.getX is bound to o, but gX, even though it's pointing at o.getX, is not bound.
