Search code examples
javascriptthisarrow-functionslexical-scope

Arrow and Lexical Scope in JS


Given the following code:

const outter = {
  inner: {
    laughter: "hahaha",
    laugh: () => {
      console.log(this) //`this` is window
    }
  }
}

const x = {
  test: function () {
    const laugh = outter.inner.laugh
    console.log(this) //`this` is x
    laugh()
  }
}

x.test()

I would expect the this inside of the laugh method to be equal to x - because we're invoking laugh from x

In the scope where we invoke laugh, this is equal to x - so it's strange that this changes in the arrow method, which should follow lexical scope.

(note, even if we change laugh to a normal function, non-arrow, this is still Window - but that makes sense)

Can anyone explain why this inside of laugh is Window?

Thanks


Solution

  • According Jason Orendorff, the guy who implemented arrow functions for Firefox, wrote the following (here):

    Arrow functions do not have their own this value. The value of this inside an arrow function is always inherited from the enclosing scope.

    The arrow function is not assigned when invoked, rather, when it's defined.

    In your example, the arrow function of the laugh property will be bound to the this in the scope it was defined in, which in your example is window.

    Update

    The OP remarked in the comments that since the arrow function is found inside an inner property of the outter [sic] object, it should pick up the scope of that object. Superficially, this is the way it should be.

    The caveat is that when creating objects, JS has to assign the property values from the inside out. In other words, the inner object literal is created first, at a time when the context of outter doesn't even exist yet!. And, therefore, since arrow functions get bound at the time of creation, the function for the outter.inner.laugh method is being bound with the context that it is found in; at the time of creating outter.inner, that would be window.