# Arrow Functions by [ kirupa](https://www.kirupa.com/me/index.htm) | filed under [JavaScript 101](https://www.kirupa.com/javascript/learn_javascript.htm) Learn about arrow functions and their awesome superpowers in conciseness and lexical scoping-ness! Before we move on, let’s address the elephant in the room. ***Arrow Functions*** is probably the coolest name for some technical thing ever. It makes the names for all of the other JavaScript concepts we’ve seen so far (and will see in the future) seem downright dreadful. With this important observation out of the way, let’s get down to business and learn about what they are and what makes them an upgrade over the traditional functions we have seen. Onwards! ## What are Arrow Functions? The best way to understand arrow functions is to dive right in, start looking at examples, and observing their behavior. On the surface, arrow functions are nothing more than an abbreviated syntax on a typical function expression. There is a whole lot more to arrow functions than just that, but we’ll start there and gradually go deeper. ### Starting with the Basics Let’s say we have a traditional function that looks as follows: ```js let laugh = function () { return "Hahahaha!"; } console.log(laugh()); // "Hahahaha!" ``` This function is called `laugh`, and it returns the text **Hahahaha!** when called. If we turned this into an arrow function, it will take on this more concise form: ```js let laugh = () => "Hahahaha!"; console.log(laugh()); // "Hahahaha!" ``` Notice what just happened: 1. We got rid of the function keyword 1. We specified an arrow (`=>`) that lives between the `()` and the `function` body 1. The curvy brackets were removed because we don't need them if our arrow function is just a single statement. Going further, if our single statement is an expression that returns a value (which is what we have), we can remove the `return` keyword as well Summarizing what just happened, we went from three lines of function-related code to just a single line. The behavior between our more verbose traditional function and the more concise arrow function is identical where calling `laugh` prints the same **Hahahaha!** to the console in both cases. ### Of Arguments and Parenthesis Building on what we just saw, if our function takes a single argument, we can remove the open/close parenthesis when defining our arrow function: ```js let laugh = name => "Hahahaha! " + name + "!"; console.log(laugh("Zoidberg")); // "Hahahaha! Zoidberg!" ``` Notice that our laugh function takes the argument `name`, and it returns the combination of `name` and **Hahahaha!**. This is the most concise form of an arrow function where we remove all of the syntactical fluff when we have just a single argument. If we add more arguments to our function, the parenthesis around the arguments will come back: ```js let laugh = (first, last) => "Hahahaha! " + first + " " + last + "!"; console.log(laugh("John", "Zoidberg")); // "Hahahaha! John Zoidberg!" ``` The main thing to keep in mind is that the way the parenthesis behave is identical to how you would treat them with traditional functions. We can specify as many arguments we want with a comma separating each individual argument. We can even specify default values for the arguments. ### To Curly Bracket or Not to Curly Bracket We mentioned earlier that we can omit the curly brackets if our function has only a single statement. If our function specifies multiple statements, the curly brackets have to be back: ```js let anotherExample = () => { console.log("Hello"); console.log("Everybody"); } anotherExample(); ``` If our function with multiple statements is returning a value, then we have to ensure the `return` keyword is used as well: ```js let anotherExample = () => { let a = "Hello "; let b = "Everybody"); return a + b; } anotherExample(); ``` When we think about it, this makes a whole lot of sense. If we have multiple statements, it is hard to know which statement contains the value that we want to return. Having an explicit `return` avoids that confusion. #### Note: Preferences May Vary! Here’s the thing. You or your team may not particularly enjoy toggling between showing brackets or using `return` or not based on what exactly the function is doing or how many statements are in it. There is nothing wrong with always displaying curly brackets and using a `return`: ```js let laugh = () => { return "Hahahaha!"; } laugh(); ``` Here is an example of our laugh function from earlier where we display both the curly brackets and the `return` keyword despite the function body having just a single expression that returns a value. This function totally works and isn't wrong at all. ### Putting it All Together Just for good measure, let’s take a lot of what we have just seen and explore one last example: ```js let calculateDiameter = (radius = 1) => { let pi = 3.14159; let diameter = 2 * pi * radius; return diameter; }; console.log(calculateDiameter(4)); // 25.13272 console.log(calculateDiameter()); // 6.28318 ``` We have a function called `calculateDiameter`, and it takes a single argument called `radius` (which has a default value of 1 that is used when we don't specify an argument.) Calling the `calculateDiameter` function with (or without) a radius argument returns the correct value. The biggest takeaway for us with arrow functions is this: ***almost*** anything you can do with traditional functions, you can do with arrow functions as well. Now, there are a few big differences, hence the emphasis on ***almost***. Arrow functions and traditional functions have different scoping behavior, and arrow functions have a few limitations that we should be aware of. We’ll get to the bottom of what’s up with all this in the next few sections. ## Arrow Functions and Scoping Brace yourself. This is going to be a sordid tale involving **variable scopes** and the value of `this`. These are two topics that, on the best of days, can make anyone's head spin. The best way to understand the differences in scoping behavior between traditional functions and arrow functions is to look at a common situation we will run into. The situation looks as follows: ```js let counter = { initial: 100, interval: 1000, startCounting: function () { setInterval(function () { this.initial++; console.log(this.initial); }, this.interval); } } counter.startCounting(); ``` We have an object called `counter`, and it has the `initial`, `interval`, and `startCounting` properties. The property that we want to focus on is `startCounting`, and it represents a function whose body is a `setInterval` function: ```js let counter = { initial: 100, interval: 1000, startCounting: function () { setInterval(function () { this.initial++; console.log(this.initial); }, this.interval); } } counter.startCounting(); ``` When someone calls `startCounting`, the idea is for us to increment the value of `initial` at a rate specified by the `interval` property. Thinking out loud, when we call `counter.startCounting()`, the value of `initial` is initially (ha!) **100**. After 1000 milliseconds (as specified by the `interval` property) elapses, the value of `initial` is incremented by 1 to be **101**. After another 1000 milliseconds, the value of `initial` becomes **102**. You get the picture. Now, if we test this code, what do you think we are going to see? What will the `console.log` statement inside our interval loop show when it prints the value of `initial` every 1000 milliseconds? As it turns out, what we will see is **not** a nice set of numbers increasing by 1 starting from 100. Instead, what we will see is **NaN** being printed over and over again: ![](https://www.kirupa.com/javascript/images/nan_this_problem_200.png) Why is this the case? We can see more details if we add a few more `console.log` statements to see what the value of `this` is inside the`startCounting` and `setInterval` functions: ```js let counter = { initial: 100, interval: 1000, startCounting: function () { console.log("startCounting:"); console.log(this); setInterval(function () { console.log("setTimeout:"); console.log(this); this.initial++; console.log(this.initial); }, this.interval); } } counter.startCounting(); ``` If we run this code, we'll see our additional information being printed to the console. The value of `this` under `startCounting` will refer to the `counter` object: ![](https://www.kirupa.com/javascript/images/startCounting_this_200.png) The value of `this` inside our`setTimeout` function will refer to the `window` object: ![](https://www.kirupa.com/javascript/images/setTimeout_this_problem_200.png) Here is where things are problematic. You may think that `setInterval` would inherit the value of `this` from its outer environment as defined by `startCounting`, but that isn't the case. The reason is that traditional functions don't behave in this seemingly logical way. They define their own value for `this` and that is always going to refer to the context they are being used in. Our anonymous function inside our `setTimeout` doesn't get created when our counter object is initialized. It gets created only when we call the `startCounting` method: ```js counter.startCounting(); ``` This call lives in the context of the `window` object. When `startCounting` is invoked and the anonymous function is created, the `this.initial` call is looking for the value of `initial` on the `window` object. That property doesn't exist there, and that is why trying to increment this non-existent variable gives us a **NaN**. There are a few ways to fix this. One approach is to store the value of `this` and pass the stored `this` value into our anonymous function: ```js let counter = { initial: 100, interval: 1000, startCounting: function () { let that = this; setInterval(function () { that.initial++; console.log(that.initial); // undefined }, this.interval); } } counter.startCounting(); ``` Notice that we introduced a `that` variable in the `startCounting` context to store a local reference to `this`. Inside our anonymous function, we use `that` where we earlier used `this`. Because `that` is properly storing a version of `this` that is tied to our `counter` object, our use of `that.initial` properly resolves to the correct value. If you run this code, you'll the output of initial properly incrementing when we examine our console: ![](https://www.kirupa.com/javascript/images/counter_works_properly_200.png) All of these mentions of ***this*** and ***that*** in this explanation can be a bit confusing, but do feel [free to ask for help](https://forum.kirupa.com) if you have any questions. We just saw one approach of addressing this problem by storing the value of `this` and using this stored value in place of the actual `this`. There is a better approach. Let's say we replace our anonymous function inside our `setInterval` with an arrow function: ```js let counter2 = { initial: 100, interval: 1000, startCounting: function () { setInterval(() => { this.initial++; console.log(this.initial); // works }, this.interval); } } counter2.startCounting(); ``` When we run this code, what gets printed this time around is 100, 101, 102...and so on just like we want. No mess. No fuss. No ***that*** and ***this*** confusion. Why does an arrow function work here while traditional functions require extra gymnastics? The reason is that arrow functions **do not** define their own `this` value. Instead, they inherit the value of `this` from where their code is ***defined*** in the document. Another way of saying this is that the `this` value inside arrow functions is determined by its surrounding scope, more formally called the **lexical scope**. This is in contrast to traditional functions whose `this` value comes from the context in which they are used in. This is a subtle difference with a huge (and beneficial) change in behavior. #### Note: Some Things Arrow Functions Don't Have Beyond not having their own `this` value (which they inherit from their surroundings), arrow functions have no `constructor` or `prototype` properties. They also don't support the `bind`, `call`, and `apply` methods. If you have existing code that relies on these properties and methods, your best is to stay with traditional functions or learn how to use arrow functions and adapt your code accordingly. ## Conclusion It is time to answer the inflation-adjusted million dollar question: ***when should we use arrow functions?*** There are several answers here. If you enjoy the abbreviated syntax arrow functions have compared to traditional functions, use it as much as you want. If you are someone who finds this abbreviated arrow functions syntax to lack the clarity of the more verbose traditional functions, you don't ever have to use it. My personal take is to be somewhere in the middle, like Malcolm! Arrow functions are great for situations where we need to provide an anonymous function as part of an event handler, timer, and so on: ```js let myButton = document.querySelector("#myButton"); myButton.addEventListener("click", () => console.log("Click!")); ``` The reason is partly for the abbreviated syntax, but the other reason is mostly because of their more sensible treatment of `this`. As we saw a few sections ago, arrow functions' treatment of `this` using the lexical scope is more predictable when compared to how traditional functions redeclare `this` and assign it to the context they are initialized and used in.