Arrow Functions and this
TIL how to leverage ES6 arrow functions to avoid losing “this” when writing functions inside of functions.
Arrow functions are more than just a syntactically shorter way of defining a function in javascript.
What’s the Difference?
Arrow functions do not bind a new this
context like functions defined with the function
keyword do.
When defining functions using the function
keyword, the binding of a new this
can lead to the loss of the intended this
when using callbacks or inner functions. For example:
In the constructGreeting
method above, the function
keyword binds a new this
context accessible in its function body that overwrites the enclosing object’s context. This overwrite causes the enclosing object’s scope to be lost inside of the constructGreeting function body. In fact, the this
bound by the inner function will actually be the global object!
A Workaround to Losing this
Before arrow functions, a common workaround for this problem was to assign the outer function’s this
to a variable (often called that
or self
). The variable that
is available for access in the inner function, and allows the inner function to access properties of the outer scope.
The inner function references outer scope properties from the closed over that
variable.
A Cleaner Solution with Arrow Functions
While the above workaround gets the job done, there is a cleaner solution if we use arrow functions. Since arrow functions do not bind a new this
context, arrow functions can still access any parent object contexts by referencing the this
keyword in their body.
The above code behaves exactly as you would expect: this
inside of the constructGreet
method refers to the containing object instead of a newly bound this
context. Not only is the above code more consisce, but it is more readable and predictable.
Nuances of Arrow Function’s Handling of this
The fact that arrow functions do not bind their own this
context has several important implications:
1) Arrow functions cannot be used as object constructors - Since arrow functions do not bind a this
context, they cannot be invoked with the new
keyword to return a new object context. In fact, trying to invoke an arrow function with the new keyword will throw a runtime error: Function is not a constructor
.
2) Arrow functions cannot be used as object methods if those methods need to reference the containing object context this
. For this reason, it is best practice to still declare object methods using the function keyword. To see an example of this issue in action, try changing the greet
method in my examples above to be an arrow function instead of a using the function
keyword… the object properties this.name
and this.salutation
are lost!
3) Arrow functions cannot be passed new contexts using call
or apply
, and cannot be bound to new contexts using bind
. If an arrow function is invoked with call
or apply
, it will ignore any new this
context passed to it, but it will still honor the function parameters passed. See the following example:
If greet were defined using the function
keyword, the bind
, call
and apply
calls above would have all bound the newContext
as its new calling context, and would have logged ‘hello Ms. Lauren’.
However, since greet was defined with an arrow function and arrow functions do not bind their own this
, all 4 calls above log ‘hello Dr. Brian’.
Click here for the MDN documentation for Arrow Functions. It was helpful in cementing my understanding.
Comments