In the previous article, we saw what arrow function is and how it can provide programmers with a more succinct, intuitive way to define a function.
In this article and those that follow, we are going to examine potential pitfalls that we should be aware of when using arrow functions. Specifically, we will focus on what this
refers to within an arrow/non-arrow function in the context of list processing and event handlers, which are indispensable aspects of all web applications.
We will also learn about how to make sense of this
in those different contexts and eliminate any confusions that we might have in terms of this
so the process of dealing with this
, both in arrow and non-arrow functions, becomes less stressful and more comfortable.
This article will centre around different behaviours of this
within the three methods we use all the time for list processing: forEach
, $.each
, and .each
.
Example code
We will use a small program to see how the value of this
changes when it appears in each of the, um, “each” methods. You can view the code hosted on CodePen here to follow along. You can also copy and paste this HTML file and test the code on your local computer.
The overall structure of the application is as follows.
The application consists of 3 links. When clicked, each link will display a div section that gives us a visual indication of what this
refers to within the callback function for forEach
, $.each
, or .each
. Within these 3 methods, we are comparing this
with 3 values: currentElement
, which is an element a method is currently iterating on; window
, which is the window
object that is located at the top of the DOM hierarchy; and App
, which is an object that contains all the application logic (Note that this
within the $.each
and each
methods actually refers to the corresponding DOM element and we have to expose the actual value contained within this
to compare it with currentElement
. The source code used the valueOf
method for this purpose. Also notice that the program wraps the array object arr
around the jQuery function ($
) to be used with the.each
method; the method can be called only on jQuery objects).
Result
For those of you who are too busy, lazy, impatient etc., to test the code, which I totally understand as I tend to be one of those people, here is how the value of this
changes within the forEach
, $.each
, and each
methods as shown by the program.
You might notice that this
within an arrow function always points to the same object, App
, regardless of the method the arrow function is used in. If we recall that this
within an arrow function is defined within a “lexical scope”, this should make sense, since the value of this
is based on where this
can be found in the source code and therefore is sort of already “fixed” once the source code is written. This is one of the reasons we should definitely welcome the creation of the arrow function with open arms; we no longer have to spend our time and energy implementing “clever” techniques, such as bind
and call
, to deal with context changes and losses.
Tradeoff
As a programmer, it’s important to pay attention to details so we can correctly use our newly found tools.
Firstly, we have to remember that the primary goal of list processing is, as its name suggests, process a list. For this reason, we need to make sure that we have access to each of the elements contained within the list; after all, what’s the point of iterating over a list of elements if we cannot access what we are iterating over?
We then realise that this
within an arrow function doesn’t provide access to each element ( currentElement
) contained within the list. If we look at Fig2 and Fig3 above, we also notice a non-arrow function (i.e. function defined with the function
keyword), which itself is used as a callback function to the $.each
and each
methods, actually has this
point to the currently iterated element, which is how the jQuery library implements the behaviour of this
and is what we have become used to by making extensive use of $.each
and .each
during our programming career.
Hélas, this
within an arrow function overwrites this default behaviour, referencing the App
object as per the location it was originally defined within the source code.
Where is the current element?
The question, then, is to know how to access each element within a list using an arrow function from within the $.each
and .each
method without the use of this
.
We can achieve this simply by relying on the default parameters of each of these methods, rather than onthis
, to access each of the elements.
For the forEach
method, we should use the first argument of its callback arrow function to access the current element like so:
For the $.each
and each
methods, we should use the second argument of its callback, arrow function to access the “value” of the current element, which is actually a Javascript object. Note that the first argument of the callback function is reserved for the index of the currently iterated element. You might want to check the MDN documentations for $.each
and each
if you are not exactly sure how these methods are implemented.
Of course, we can choose not to use an arrow function for the callback function for either $.each
and .each
and instead turn to the non-arrow function
and rely on the default value of this
implemented by jQuery to reference the value (object) of currently iterated element.
Bottom line
While a concise and intuitive code provided by arrow function is quite powerful and programmer-friendly, we have to make sure this
refers to what we should expect it to. For jQuery methods in particular (i.e. $.each
and each
), we should be careful when using an arrow function as a callback function since it overwrites the default implementation of this
pointing to the currently iterated element (object), a behaviour we usually rely on when using these methods . If you decide to use an arrow function as a callback function for either $.each
or .each
, make sure to use its second argument to reference the currently iterated value. If you choose to adopt a non-arrow function as a callback function, you can safely use this
to access the object you are currently iterating on within these methods.
As always, any suggestions on how the article can be improved (e.g. better example code, bugs, errors, typos, etc) will be greatly appreciated!