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 trialJeff Mignone
15,395 PointsArrow 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
56,413 PointsI'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
231,198 PointsI'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.
Jeff Mignone
15,395 PointsIf 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
231,198 PointsSo "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".
Jeff Mignone
15,395 PointsThanks 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.
Alexander La Bianca
15,959 PointsIn 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
231,198 PointsIt's obj2 that is logged out. The fact that foo2 is not logged out shows that it is execution scope that establishes "this".
Steven Parker
231,198 PointsSteven Parker
231,198 PointsExcellent clarification.