This article explains this and its use in JavaScript, using simple terms and real-world examples, and shows you why writing good code is so important.

1. Does this suit you?

I’ve seen many articles that introduce JavaScript’s this assuming you’ve learned some kind of object-oriented programming language, such as Java, C++, or Python. But this article is written for people who don’t know what this is. I’ll try not to use any jargon to explain what this is and how this is used.


Maybe you’ve been afraid to solve the mystery of this because it looks weird and scary. Maybe you only use it when StackOverflow says you need it (such as when implementing a feature in React).

Before we dive into this, we need to understand the difference between functional and object-oriented programming.

Functional programming vs. object-oriented programming


You may not know that JavaScript has both object-oriented and functional structures, so you can choose which style to use, or both.


I loved functional programming long ago in JavaScript and avoided object-oriented programming like the plague because I didn’t understand the keywords in object-oriented programming, such as this. I don’t know why I use this. It seems I can do all my work without it.


And I was right.


In a sense. Maybe you can focus on one structure and ignore the other completely, but then you’re only a JavaScript developer. To illustrate the difference between functional and object-oriented, let’s use an array of Facebook friends.


Suppose you want to make a Web application, and when users log into your Web application using Facebook, they need to display their Facebook friends. You need to access Facebook and get the user’s friends data. This data could be firstName, lastName, username, numFriends, friendData, Birthday, and lastTenPosts.

Let’s say you get that data from the Facebook API. Now you need to convert it into a format that is convenient for your project. Let’s assume you want to display the following friend information:


  • Name in the format of ‘${firstName} ${lastName}’

  • Three random articles

  • Number of days until birthday

3. Functional approach

The functional way is to pass the entire array or an element of the array to a function and return the information you need:


First we have the raw data returned by the Facebook API. To convert it to the desired format, the data is first passed to a function whose output is (or contains) modified data that can be displayed to the user in the application.


We can use a similar method to get three random articles and count the number of days until your friend’s birthday.


The functional way is to pass raw data to one or more functions to get the data format that is useful to your project.

4. Object-oriented approach

For beginners in programming and JavaScript, the concept of object orientation can be a little difficult to understand. The idea is that we’re going to turn every friend into an object that generates everything you need as a developer.


You can create an object that corresponds to a friend, has a fullName attribute, and two functions getThreeRandomPosts and getDaysUntilBirthday.

The object-oriented approach is to create objects for the data, each of which has its own state and contains the necessary information to generate the required data.

5. What does this have to do with this?

You might never have thought to include the initializeFriend code above, and you might think it would be useful. But as you’ll notice, this isn’t really object-oriented.


The reason why getThreeRandomPosts or getdaysUntilBirtyday in the example above works is because of closures. Because they use closures, they can access data even after initializeFriend returns. More information about the closure can take a look at this article: scope and closure (https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md).


There’s another way to do this, right? Let’s assume that this method is called greeting. Note that a method (a method associated with a JavaScript object) is really just a property, except that the property value is a function. We want to implement the following functionality in Greeting:


Does that work?


Can’t!


Our new object has access to all the variables in initializeFriend, but not to the properties or methods of the object itself. Of course you ask,


Can’t you use data.firstName and data.lastName directly in greeting?


B: Sure. But what if you want to add the number of days from your friend’s birthday to the greeting? We better have a way to call getDaysUntilBirthday in greeting.


And now it’s this’s turn!


6. Finally — What is this

This can mean different things in different contexts. By default, this refers to the global object (this is the Window object in the browser), which is not very useful. The only practical rule of this is this:


If you use this in a method of an object that is called in the context of that object, this refers to the object itself.


You would say “called in the context of that object”… What does that mean?



Don’t worry. We’ll talk in a minute.


So, if we want to call in the greeting getDaysUntilBirtyday we only need to write this. GetDaysUntilBirthday, because this is the object itself.


Note: Do not use this in the scope of an ordinary function in the global scope or another function. This is an object-oriented thing that only makes sense in the context of an object (or a class).


We use this to rewrite initializeFriend:


function initializeFriend(data) { return { lastTenPosts: data.lastTenPosts, birthday: data.birthday, fullName: `${data.firstName} ${data.lastName}`, getThreeRandomPosts: function() { // get three random posts from this.lastTenPosts }, getDaysUntilBirthday: function() { // use this.birthday to get the num days until birthday }, greeting: function() { const numDays = this.getDaysUntilBirthday() return `Hello, this is ${this.fullName}’s data! It is ${numDays} until ${this.fullName}’s birthday! `}}; }


Now, after the initializeFriend execution, everything that the object needs is in the scope of the object itself

The inside. Our methods no longer rely on closures; they only use the information contained in the object itself.


Ok, that’s one of the uses of this, but you said this has different meanings in different contexts. What does that mean? Why doesn’t it necessarily point to the object itself?


Sometimes, you need to refer this to something specific. One case is event handlers. For example, we want to open a friend’s Facebook home page when the user clicks on it. We will add the following to the object

OnClick method:


function initializeFriend(data) { return { lastTenPosts: data.lastTenPosts, birthday: data.birthday, username: data.username, fullName: `${data.firstName} ${data.lastName}`, getThreeRandomPosts: function() { // get three random posts from this.lastTenPosts }, getDaysUntilBirthday: function() { // use this.birthday to get the num days until birthday }, greeting: function() { const numDays = this.getDaysUntilBirthday() return `Hello, this is ${this.fullName}’s data! It is ${numDays} until ${this.fullName}’s birthday! ` }, onFriendClick: function() { window.open(`https://facebook.com/${this.username}`) } }; }


Notice that we added the username property to the object so that onFriendClick can access it and open the friend’s Facebook home page in a new window. Now you just need to write HTML:

There are JavaScript:

In the code above, we create an object for Bob Ross. And then we get the DOM element for Bob Ross. Then execute the onFriendClick method to open Bob’s Facebook home page. Seems ok, right?


There is a problem!


What went wrong?


Note that our code for calling the onclick handler is bobrossobj.onfriendclick. See the problem? Can you tell if it’s written like this?


See the problem now? If you write your event handler as bobrossobj.onfriendclick, you are actually taking the function saved on bobrossobj.onfriendclick and passing it as an argument. It’s no longer “attached” to bobRossObj, that is, this no longer refers to bobRossObj. It actually points to the global object, which means this.username doesn’t exist. There seems to be nothing we can do.


It’s binding’s turn!


7. Explicitly bind this

We need to explicitly bind this to bobRossObj. We can do this with bind:


Previously, this was set to the default rule. But using bind, we explicitly set the value of this in bobrossobj.onfriendclick to the bobRossObj object itself.


So far, we’ve seen why we use this and why we bind this explicitly. Finally, this is actually the arrow function.

Arrow function

You may have noticed that arrow functions are very popular these days. People like the arrow function because it’s simple and elegant. And you also know that arrow functions are a little different from normal functions, although it’s not clear exactly what the difference is.


In a nutshell, the difference is:


When you define an arrow function, no matter who this points to, the this inside the arrow function always points to the same thing.


HMM… This doesn’t seem to help… Seems to behave like a normal function, right?


Let’s use initializeFriend as an example. Suppose we want to add a function called greeting:


Does that work? If not, how can I modify it to run?


The answer is no. Because getLastPost is not called in the context of the object, this in getLastPost points to the global object by default.


You say there is no “call in the context of an object”… Isn’t it an internal call returned from initializeFriend? If this isn’t called “calling in the context of an object,” THEN I don’t know what is.


I know the term “called in the context of an object” is vague. Perhaps a good way to determine if a function is “called in the context of an object” is to review the function call and see if an object is “attached” to the function.


Let’s check bobrossobj.onfriendClick (). “Give me the object bobRossObj, find the onFriendClick and call the function corresponding to that property.”


Let’s also check for getLastPost(). “Give me a function called getLastPost and execute it.” See? We didn’t mention the object at all.


Okay, here’s a puzzle to test your understanding. FunctionCaller (); functionCaller (); functionCaller ();


What if functionCaller(bobrossobj.onfriendclick) is called? Would you consider onFriendClick “called in the context of an object”? Is this.username defined?


Let’s check this: “Give me the bobRosObj object and look for its property onFriendClick. Fetch the value (which happens to be a function) and pass it to the functionCaller, named fn. Then, the function named fn is executed.” Note that this function is “removed” from the bobRossObj object before it is called, so it is not “called in the context of the object”, so this.username is not defined.


The arrow function can be used to solve the problem:


The rules for the above code are:


When you define an arrow function, no matter who this points to, the this inside the arrow function always points to the same thing.


The arrow function is defined in greeting. We know that the this inside the greeting refers to the object itself. Therefore, the this inside the arrow function also points to the object itself, which is exactly what we want.

9, conclusion

This is sometimes hard to understand, but it’s very useful for developing JavaScript applications. This article certainly does not cover all aspects of this. Some topics not covered include:


  • Call and apply;

  • What happens to this when we use new;

  • What happens to this in ES6 class.


I suggest you first ask yourself about this in these cases, and then run the code in the browser to verify your results.


This article was transferred to the public account CSDN (ID: CSDNnews) by permission.

Austin Tackaberry, Software Engineer at Human API

Original link: https://medium.freecodecamp.org/a-deep-dive-into-this-in-javascript-why-its-critical-to-writing-good-code-7dca7eb489e7