The Mystery of _this2

this, arrow functions, and debugging in Babel transpiled code

During a recent project I found myself frustrated trying to discover what this was throughout various methods. this is a concept that confuses all Javascript developers. A very brief understanding of this is that when a function executes, it gets the this property — a variable with the value of the object that invokes the function where this is used. This may seem easy to understand however once we start using functions the concept of this likes to change.

Above we see a simple explanation of what this is at various points:

  1. this defaults to the Window when declared in global scope.
  2. We declare a new instance of whatIsThis.
  3. whatIsThis console.logs line 6.
  4. console.log states this is the current class whatIsThis.
  5. Whenever you create a new instance the console returns the new object.

Let’s add a method to our class to see how this can suddenly get away from us:

  1. We declare a new instance of whatIsThis and assign it to what.
  2. The return value of creating a new instance is undefined as expected.
  3. we call the changeThis method on our new instance.
  4. The changeThis method returns an anonymous function that returns this.

What? Why is this undefined now? Well, since that we declared a function and referred to this inside of it the scope has changed.


Arrow Functions

With the introduction of ES6, Javascript introduced a new kind of function; arrow functions.

An arrow function expression has a shorter syntax compared to function expressions and does not bind its own this, arguments, super, or new.target. Arrow functions are always anonymous. These function expressions are best suited for non-method functions and they can not be used as constructors.
- MDN on arrow functions

Arrow functions eliminate the issue we were facing before and this will keeps its scope inside of an arrow function.

  1. We create a new instance of Test and assign it to test.
  2. The return value of creating a new instance is undefined as expected.
  3. We call the regularFunction method on test.
  4. It returns this which is undefined because it is a regular function.
  5. We call the arrowFunction method on test.
  6. It returns this which is the class Test because arrow functions keep the scope.

Debugging with Babel and what is _this2 ?

Babel is a great compiler for Javascript that allows you to use new Javascript syntax without worrying about if browsers are supporting it.

From the Babel website

This means that we can use Javascript’s new arrow functions, have more confidence in the scope of this, and not worry about the environment in which our code is being run. While Babel transpiles our code into readable Javascript by all browsers, it’s functionality can also have unintended consequences when we use Javascript’s debugger.

A way to stop our code at certain moments in time and see the state of our code is essential in any developing language. The issue with using transpilers like Babel is that it alters our code from its original state.

**The following code is using React to create an app that displays pets in a PetBrowser component. For complete understanding, it requires a basic knowledge of React although the ideas should still be present without knowledge of React.

Here is snippet from the app that is cycling over the PetBrowser’s props and creating Pet components with a pet prop. There are two debuggers at line 11 and line 14. On line 13 I assign var that = this for demonstration purposes. Arrow functions have eliminated the need to do this.

Code
Sources tab
Console tab

When the above code is run we hit our first debugger on line 11. In the console we can check the return value of this which at this point in time is the PetBrowser component. To continue on we press continue and hit our next debugger at line 14. At this point in time we are inside of a map function that was originally created as an arrow function but Babel as transpiled it into a regular function.

Our original code
Babel’s transpiled code

Let’s check the return value of that and this

return value of that
return value of this. Huh?

The return value of that is exactly what we expected because we assigned it to this. But the return value of this is undefined? How is that possible? that and this are on the same line in our original code yet they have different return values. If you take a closer look you will see what babel does when it transpiles arrow functions into regular functions.

Where did those variable assignments come from? Babel

In order for Babel to keep the functionality of arrow functions, AND transpile them into regular functions it has to reassign this to the mysterious _this2. Basically Babel is taking care of the var that = this for us.

This means that if we are debugging code that uses Babel to transpile, we are going to have to look at our Elements tab in the Developer Console if we want to see the appropriate return value for this.

Our original
Babel transpiled code in the Elements tab
The return values in the Console tab

In the above code we are fetching from an api and have placed a debugger on line 36. If we wanted to see what the current state was at this point in time we cannot use this.state because at this point in time this is undefined. We would have to call _this2.state to check the current state. Remember this is only for debugging purposes. We should NEVER use _this2 in our original code.

Being able to debug our code is one of the most important skills we have as developers. Understanding exactly what transpilers like Babel are doing when it renders our code is essential to debugging properly.