Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Arrow functions and 'this'

I understand that arrow functions don't have their own this but they inherit a this from their parent scope based on where they are defined (from what I've read). What I'm confused on is why in my first example foo the arrow function returns the window object, but in the second example, the arrow function console.logs obj2. Arrow function lexical scoping makes sense to me when the method or function is already on an object, but when I insert it like these examples, it confuses me.

1

var foo = () => console.log(this);

var obj = {
    prop1: function() {
        return foo;
    }
}

obj.prop1()();

2

var foo2 = function() {
    return () => {
        console.log(this);
    }
}

var obj2 = {
    bar: foo2
}

obj2.bar()();

3 Answers

Seth Kroger
Seth Kroger
56,413 Points

I'm afraid I have to take issue with this. It is exactly right that an arrow function's this is based on where it's defined, not how it's called. The tricky part is when it's defined. Remember that JavaScript is an interpreted language and that functions, regular or arrow, aren't created when you write them, but when the JavaScript engine runs the code that creates them.

As the MDN page states: "An arrow function does not have its own this; the this value of the enclosing execution context is used." i.e. the context where the arrow function is defined, not the context where the arrow function's code is executed/called. In the first example when var foo = () => console.log(this); is executed, the current value of this is used, which is window to create a function that is stored in foo. Since an arrow function's this can't be altered, it's pretty much the same as writing var foo = () => console.log(window); Thus, when we call the higher-order function prop1() we'll always be returned () => console.log(this=window)

The second example is a bit different because foo2 returns a new arrow function created inside of itself when called instead of an single arrow function stored in an external value. Also because foo2 is a regular function, its this is from the calling execution context and can change from call to call. So when we call foo2() as obj2.bar() this is obj2 when we define the arrow function and we get returned () => console.log(this=obj2). If we call foo2() directly from the global scope, then this is window when we define the arrow function and we are returned a separate arrow function of () => console.log(this=window). Like any other arrow function, its this will remain unchanged no matter how it's called.

obj2.bar2 = foo2()
obj2.bar2()  // Logs window, not obj2

Also: Closures

Steven Parker
Steven Parker
231,269 Points

Excellent clarification. :+1:

Steven Parker
Steven Parker
231,269 Points

I'm not sure where you read otherwise, but in an arrow function, "this" is based on "the this value of the enclosing execution context".

So in your second example, the function is being executed in the context of the object "obj2", so that's the value "this" takes on.

But if you were to call it like this, it would again log the Window object:

foo2()();

See the MDN page for more details.

If it's always execution context, then could you explain to me how in example 1 returning foo when running obj.prop1()(); gives the window object? Shouldn't it inherit its this from the prop1 method?

Steven Parker
Steven Parker
231,269 Points

So "prop1" executes in the context of "obj" and returns "foo". But then executing "foo" is done from the Window context.

I agree it's pretty confusing. Perhaps this is why the doc page says these "are best suited for non-method functions".

Thanks Steven for your help. After thinking about it a little bit...what I think might be happening is if a function is defined with arrow functions within it, the parent scope must be resolved first in order for the arrow function to inherit its this. In example 1, since I just wrote return foo, it's the same as saying return window.foo since foo was defined by itself in the global scope. In example 2, foo2 was defined in the global scope with an arrow function inside of it. However, foo2 moves as a unit. When foo2 is assigned to bar the parent scope of foo2 is bound to obj2, as per normal this rules. However, the inner arrow function can now resolve its this by looking up one level to the parent scope and inheriting that value which is obj2.

In example 1, because you are using an arrow function - the global window object is used as you are returning a reference to the function foo which is defined in the global scope. And you are then executing the function by doing obj.bar()();

Your second example, foo2 is the scope of the function you are returning which is why foo2 is the one that is logged out.

Steven Parker
Steven Parker
231,269 Points

It's obj2 that is logged out. The fact that foo2 is not logged out shows that it is execution scope that establishes "this".