This cheatsheet you need

This cheatsheet you need

The most dumbed down definition I have is: 'this' is the object that calls a function or the object where an arrow function is called

A more technical study is dynamic scope vs lexical scope;

Who is 'this' in the for each function call?

    // 1. this in a function
    function mySingleFunc() { console.log(this) } // this is the Global object

    // 2. this in a constructor function
    const myObject = new function(){ this } // this is the new object 'myObject'

    // 3. this in an object method function
    myObject.myFunc = function() { console.log(this) } // this is myObject
    myObject.myFunc();

    // 4. this in an inner function of an object method function
    myObject.myFunc = function() {
              const innerFunction = function() { console.log(this) } // this is the Global object
              innerFunction(); 
     }
    myObject.myFunc();

    // 5. this in an async function callback in an object method function
     myObject.myFunc = function() {
              setTimeout(function() { console.log(this) }, 0) // this is the Global object
     }
     myObject.myFunc();

    // 6. this in an object method arrow function
    myObject.myArrowFunc = () => { console.log(this) } // this is the Global object
    myObject.myArrowFunc();

    // 7. this in a inner arrow function in an object method function
    myObject.myFunc = function() {
              const innerArrowFunction = () => { console.log(this) } // this is myObject
              innerArrowFunction(); 
     }
    myObject.myFunc();

    // 8. this in an async arrow function callback in an object method function
    myObject.myArrowFunc =() => {
              setTimeout(() => { console.log(this) }, 0) // this is the Global object
     }
    myObject.myArrowFunc();

    // 9. this in a inner arrow function in an object method arrow function
    myObject.myArrowFunc =() => {
              const innerArrowFunction = () => { console.log(this) } // this is the Global object
              innerArrowFunction(); 
     }
    myObject.myArrowFunc();

Checkout this plunk for the live examples

Let's dig deeper

You should know by now that when you call myObj.myFunc(), the this in myFunc() is myObj. myObj is the scope of myFunc;

This is an important concept to keep in mind in order to know who does what.

Whenever you declare a simple function myFunc() {} at the root level of your code, that function is automatically bound to the Global scope. Which means that whenever you call that function by name, ex: myFunc() what happens behind the scenes is actually window.myFunc() in the browser or global.myFunc() in nodeJs.

    myFunc() === window.myFunc()

But when you assign a function to a property of an object (myObj.myFunc = function() {}), that function becomes a method of that object and also is bound to that object. That's why, the this in that function is myObj, and myObj is the scope of myFunc.

Keep in mind, that if you declare/call a function (myInnerFunc) inside a method of an object, it's like you're calling myObj.myFunc() and then inside myFunc, you are actually doing window.myInnerFunc(), because myInnerFunc is not bound to myObj but just declared inside a method of that object. And that's why, the this inside the inner function is actually the global object. Same applies for callbacks of setTimeout, setInterval, or other async stuff you might do inside your function.

However, things change for arrow functions () => {}, as these functions don't have their own this binding and they shouldn't even be used as methods.

That's why, if you declare a method as an arrow function, altough the call looks like myObj.myArrowFunc() and you might think this is myObj, myArrowFunc will actually take the this from the scope in which it is called, and in this case, this will be the global object. They borrow their this from the wrapping scope in which the function is called. Same happens if there is an inner arrow function inside the method arrow function: it will be called in the scope of myArrowFunc which is the global one.

But, if you have a myFunc: function(){} method of an myObj object and inside you have myArrowFunc arrow function, the this of the arrow function will be the actual myObj, because myFunc will have a scope that is myObj, and the arrow function will be called in the myObj scope. Same happens if you have an arrow function as a callback inside an async function. The scope in which it will be called, it will still be myObj.

That's about it. Play with the examples and see for yourselves.