Search code examples
javascriptecmascript-6closuresarrow-functions

I am confused with the 'this' keyword in arrow function for this case


I have two cases and I am confused with the output I am getting.

Case 1 :

let x = {
  b: 5,
  y: function a() {
    return function() {
      return () => {
        console.log(this);
      }
    }
  }
}
x.y()()();

On running x.y()()() I am getting Window object as output but according to arrow function's definition, the output should have been its parent function.

Case 2 :

let x = {
  b: 5,
  y: function a() {
    return () => {
      console.log(this);
    }
  }
}
x.y()();

If I remove one level of nesting which is a basic example then on running x.y()(), I am getting object x as output.

Can you please explain why exactly am I getting these output?


Solution

  • The this inside a function is determined by its calling context, and by whether the function is an arrow function or not.

    With an arrow function, this is always inherited from the outer scope.

    If the function being called is a full function and that function is being called as a property as an object (eg obj.foo()), then the calling context, the this inside the foo function, is obj.

    If the function being called is a full function but is standalone - that is, not a property of an object - then there is no calling context, and this inside the function will be undefined or the global object.

    With

    let x = {
      b: 5,
      y: function a() {
        return function() {
          return () => {
            console.log(this === window);
          }
        }
      }
    }
    x.y()()();

    The this is what the returned function's this is - that is, the calling context for the function invoked here:

    x.y()()
    

    The function being invoked is not part of an object - it's a standalone function expression which was created from the invocation of a prior function on an object, equivalent to:

    (x.y())()
    

    So, there is no calling context, and this is the global object.

    In contrast, in case 2, the closest ancestor function being called is the a function on the y property of the object, and this function is called with a calling context:

    x.y()()
    ^^^^^
    

    Above, y is called with a calling context of x, so this is x inside the a function.