0

I read about the ES6 arrow function's scope in the https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#call_apply_and_bind

While I feel like it does sufficiently explain how an arrow function works. when I read these 2 example code below, I still don't quite understand why the traditional way of calling functions are able to get window as this.

Traditional Example (taken from MDN web docs):

var obj = {
    count : 10,
    doSomethingLater : function (){
        setTimeout(function(){ // the function executes on the window scope
            this.count++;
            console.log(this.count);
        }, 300);
    }
}

obj.doSomethingLater(); // console prints "NaN", because the property "count" is not in the window scope.

Arrow Example (taken from MDN web docs):

var obj = {
    count : 10,
    doSomethingLater : function(){ // of course, arrow functions are not suited for methods
        setTimeout( () => { // since the arrow function was created within the "obj", it assumes the object's "this"
            this.count++;
            console.log(this.count);
        }, 300);
    }
}

obj.doSomethingLater();

After seeing the above 2 examples, I played around a bit and wrote this, let's call this example 3:

var obj = {
    count : 10,
    doSomethingLater : function (){
        // this.count is not undefined here
        function namedFn(){ 
            console.log(this.count);
            console.log(this);  //why is this window?
        }

        namedFn();
    }
}

obj.doSomethingLater();

Now, I also read that let's say we have function A, and function B is declared within function A, function B's scope is enclosed in function A. something like this:

 // global scope
    function foo(a) {
        //foo scope
        var b = a * 2;
    
        function bar(c) {
            // bar scope
            console.log( a, b, c );
        }
    
        bar(b * 3);
    }
    
    foo( 2 ); // 2 4 12

So inside bar, I understand we still know what a is even though a is not defined in that scope. What am I missing in concepts that makes Example 3's inner console.log to be undefined and this to be window? How is it able to grab a global scope when it is within another function?

As for the 2 questions that this is marked as a duplicate of: 1 was asking why arrow function's this is referring to its parent scope. Which I think it's clear that I'm not asking that. 2 was a very generic question of "what this key work does"? Maybe this question can be a sub-section of that? but to say a generic question asking what "this" does is a dupe is a little stretch.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Angela P
  • 1,939
  • 2
  • 14
  • 18
  • 1
    Doesn't look like anything is `undefined` in the last example. – Pointy Aug 18 '21 at 16:22
  • 4
    When you call a traditional function without doing something to set `this`, the `this` binding for the call is set to a default value. In loose mode, that value is the global object (`window` on browsers, loosely). (In strict mode, it's `undefined`.) `setTimeout` calls the function without setting `this`, so that's why you see that with traditional functions. With arrow functions, though, they don't have a `this` binding; instead, they *close over* the `this` in their parent scope. Since the `this` in the parent scope above is `obj` when you do `obj.doSomethingLater()`, that's what they use. – T.J. Crowder Aug 18 '21 at 16:23
  • Re your last example: `a` and `b` would be a bit analogous to `this` if `bar` were an arrow function, but *not* if it's a traditional function, which gets `this` set based on *how it's called*, not where it's defined. – T.J. Crowder Aug 18 '21 at 16:25
  • @Pointy in example 3, this.count is undefined – Angela P Aug 18 '21 at 16:57
  • @T.J.Crowder I suspected that it's something to do with setTimeout, which is why in my example 3, I got rid of setTimeout and was surprised that it's still the same as before. – Angela P Aug 18 '21 at 17:03
  • 2
    @AngelaP - It's not specifically `setTimeout`, it's any time a traditional function is called without setting `this`; it just happens that `setTimeout` calls functions that way. When you do `example()`, `this` gets its default value (if `example` is a traditional function). In contrast, `x.example()` or `example.call(x)` set `this`. (This is what's explained in detail in the "how does the `this` keyword work?" question's answers.) Happy coding! – T.J. Crowder Aug 18 '21 at 17:08
  • 1
    arrow function doesnt assume object is `this`. Arrow function doesnt have any `this` and you cant even make it think that with something like `bind`, `apply` or `call`. It will be always window. – The Fool Aug 21 '21 at 07:50

0 Answers0