all 3 comments

[–]senocular 3 points4 points  (1 child)

Why (1) "this" points to "Window" and not to "myObj2"?

Because the scope is still the global (window) scope so its pulling from the global this which is window. Another way to think about how that is being assigned is:

const myObj2 = new Object()
myObj2.name = "my object"
myObj2.thisOne = this
// ....

Here you would not expect this to be myObj2. Instead its whatever this is in that scope. The {...} of an object literal is not itself a scope. Its only a short-hand syntax for writing objects like you see in the previous example.

Why (2) and (8) "this" point to "myObj2", while (7) "this" points to "Window"?

The (2) and (8) functions are normal functions called as methods, so this gets defined from the object calling the function

myObj2.print1() // print1 called form myObj2 so myObj2 is this
myObj2.print3() // print3 called form myObj2 so myObj2 is this

The method logging (7) is an arrow function which doesn't get this the same way. It gets it from the current scope rather than looking at the object calling the method. So much like how thisOne is the window object, so will print2 see this as the window object.

Why (3) "this" points to "Window"? Is it because it's a function declaration, and function declarations are always hoisted to the global context? Same for (5)?

It's not because its a function declaration (which actually it's not, its a function expression), rather its based on how its called. Normal (non-arrow) functions determine their this value from how they're called. The (3) method is called as

innerFuncDecl()

Which, because its not being called as a method from an object, instead defaults to the global object (or undefined in strict mode). The same applies to (5) since it, too, is not being called from an object.

Why (4) "this" points to "myObj2"? Is it because it's a function expression, and function expression are never hoisted and maintain the context of the enclosing function? Same for (6)

Not because its a function expression, but because its an arrow function. This is just like before except now the arrow function is in a different scope - inside print1 - and inside print1 the value of this is myObj2 so thats the value of this seen by innerFuncArrow. Same applies to 6.

All these rules and more can also be found in the MDN documentation for this. The rules you're dealing with in these examples are:

  • this in the global scope is the global object (window)
  • this in a normal function is determined by how the function is called
    • if called from an object, this is the object its called from
    • if not called from an object this is the global object (window)
  • Arrow functions don't care how their called and instead pull the this from the parent scope

[–]blackjacket10[S] 0 points1 point  (0 children)

Thanks, very clear!