Introducing Arrow Functions
Arrow functions, or Fat arrow functions, are a new way to create functions in ECMAScript 6. Arrow functions simplify function syntax. They are called fat arrow functions because they are denoted with the characters =>, which, when put together look like a fat arrow. Arrow functions in JavaScript are frequently used in callback chains, promise chains, array methods, in any situation where unregistered functions would be useful.
The key difference between arrow functions and normal functions in JavaScript is that arrow functions are anonymous. Arrow functions are not named and not bound to an identifier. This means that an arrow function is created dynamically and is not given a name like normal functions. Arrow functions can however be assigned to a variable to allow for reuse.
When creating an arrow function, all we need to do is remove the function keyword and place an arrow between the function arguments and function body. Arrow functions are denoted with the following syntax:
( arg1, arg2, ..., argn ) => { /* Do function stuff here */ }
Snippet 1.13: Arrow function syntax
As you can see from the preceding syntax, arrow functions are a more concise way of writing functions in JavaScript. They can make our code more concise and easier to read.
Arrow function syntax can also vary, depending on several factors. Syntax can vary slightly depending on the number of arguments passed in to the function, and the number of lines of code in the function body. The special syntax conditions are outlined briefly in the following list:
Single input argument
No input arguments
Single line function body
Single expression broken over multiple lines
Object literal return value
Exercise 3: Converting Arrow Functions
To demonstrate the simplified syntax by converting a standard function into an arrow function, perform the following steps:
Create a function that takes in parameters and returns the sum of the two parameters. Save the function into a variable called
fn1
.Convert the function you just created to an arrow function and save into another variable called
fn2
.To convert the function, remove the
function
keyword. Next, place an arrow between the function arguments and the function body.Call both functions and compare the output.
Code
index.js:
const fn1 = function( a, b ) { return a + b; }; const fn2 = ( a, b ) => { return a + b; }; console.log( fn1( 3 ,5 ), fn2( 3, 5 ) );
Snippet 1.14: Calling the functions
Outcome
You have successfully converted normal functions into arrow functions.
Arrow Function Syntax
If there are multiple arguments being passed in to the function, then we create the function with the parentheses around the arguments as normal. If we only have a single argument to pass to the function, we do not need to include the parentheses around the argument.
There is one exception to this rule, and that is if the parameter is anything other than a simple identifier. If we include a default value or perform operations in the function arguments, then we must include the parentheses. For example, if we include a default parameter, then we will need the parentheses around the arguments. These two rules are shown in the following code:
// Single argument arrow function arg1 => { /* Do function stuff here */ } // Non simple identifier function argument ( arg1 = 10 ) => { /* Do function stuff here */ }
Snippet 1.15: Single argument arrow function
If we create an arrow function with no arguments, then we need to include the parentheses, but they will be empty. This is shown in the following code:
// No arguments passed into the function ( ) => { /* Do function stuff here */ }
Snippet 1.16: No argument
Arrow functions can also have varied syntax, depending on the body of the function. As expected, if the body of the function is multiline, then we must surround it with curly braces. However, if the body of the function is a single line, then we do not need to include the curly braces around the body of the function. This is shown in the following code:
// Multiple line body arrow function ( arg1, arg2 ) => { console.log( `This is arg1: ${arg1}` ); console.log( `This is arg2: ${arg2}` ); /* Many more lines of code can go here */ } // Single line body arrow function ( arg1, arg2 ) => console.log( `This is arg1: ${arg1}` )
Snippet 1.17: Single line body
When using arrow functions, we may also exclude the return keyword if the function is a single line. The arrow function automatically returns the resolved value of the expression on that line. This syntax is shown in the following code:
// With return keyword - not necessary ( num1, num2 ) => { return ( num1 + num2 ) } // If called with arguments num1 = 5 and num2 = 5, expected output is 10 // Without return keyword or braces ( num1, num2 ) => num1 + num2 // If called with arguments num1 = 5 and num2 = 5, expected output is 10
Snippet 1.18: Single line body when value is returned
Since arrow functions with single expression bodies can be defined without the curly braces, we need special syntax to allow us to split the single expression over multiple lines. To do this, we can wrap the multi-line expression in parentheses. The JavaScript interpreter sees that the line are wrapped in parentheses and treats it as if it were a single line of code. This is shown in the following code:
// Arrow function with a single line body // Assume numArray is an array of numbers ( numArray ) => numArray.filter( n => n > 5).map( n => n - 1 ).every( n => n < 10 ) // Arrow function with a single line body broken into multiple lines // Assume numArray is an array of numbers ( numArray ) => ( numArray.filter( n => n > 5) .map( n => n - 1 ) .every( n => n < 10 ) )
Snippet 1.19: Single line expression broken into multiple lines
If we have a single line arrow function returning an object literal, we will need special syntax. In ES6, scope blocks, function bodies, and object literals are all defined with curly braces. Since single line arrow functions do not need curly braces, we must use the special syntax to prevent the object literal's curly braces from being interpreted as either function body curly braces or scope block curly braces. To do this, we surround the returned object literal with parentheses. This instructs the JavaScript engine to interpret curly braces inside the parentheses as an expression instead of a function body or scope block declaration. This is shown in the following code:
// Arrow function with an object literal in the body ( num1, num2 ) => ( { prop1: num1, prop2: num2 } ) // Returns an object
Snippet 1.20: Object literal return value
When using arrow functions, we must be careful of the scope that these functions are called in. Arrow functions follow normal scoping rules in JavaScript, with the exception of the this
scope. Recall that in basic JavaScript, each function is assigned a scope, that is, the this
scope. Arrow functions are not assigned a this
scope. They inherit their parent's this
scope and cannot have a new this
scope bound to them. This means that, as expected, arrow functions have access to the scope of the parent function, and subsequently, the variables in that scope, but the scope of this
cannot be changed in an arrow function. Using the .apply()
, .call()
, or .bind()
function modifiers will NOT change the scope of an arrow function's this
property. If you are in a situation where you must bind this
to another scope, then you must use a normal JavaScript function.
In summary, arrow functions provide us with a way to simplify the syntax of anonymous functions. To write an arrow function, simply omit the function keyword and add an arrow between the arguments and function body.
Special syntax can then be applied to the function arguments and body to simplify the arrow function even more. If the function has a single input argument, then we can omit the parentheses around it. If the function body has a single line, we can omit the return
keyword and the curly braces around it. However, single-line functions that return an object literal must be surrounded with parentheses.
We can also use parentheses around the function body to break a single line body into multiple lines for readability.
Exercise 4: Upgrading Arrow Functions
To utilize the ES6 arrow function syntax to write functions, perform the following steps:
Refer to the
exercises/exercise4/exercise.js
file and perform the updates in this file.Convert
fn1
with basic ES6 syntax.Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.
Convert
fn2
with single statement function body syntax.Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.
Remove the curly braces
({})
around the function body. Remove the return keyword.Convert
fn3
with Single input argument syntax.Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.
Remove the parentheses around the function input argument.
Convert
fn4
with no input argument syntax.Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.
Convert
fn5
with object literal syntax.Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.
Remove the curly braces
({})
around the function body. Remove the return keyword.Surround the returned object with parentheses.
Code
index.js:
let fn1 = ( a, b ) => { … }; let fn2 = ( a, b ) => a * b; let fn3 = a => { … }; let fn4 = () => { … }; let fn5 = ( a ) => ( … );
Snippet 1.21: Arrow function conversion
Outcome
You have successfully utilized the ES6 arrow function syntax to write functions.
In this section, we introduced arrow functions and demonstrated how they can be used to greatly simplify function declaration in JavaScript. First, we covered the basic syntax for arrow functions: ( arg1, arg2, argn ) => { /* function body */ }
. We proceeded to cover the five special syntax cases for advanced arrow functions, as outlined in the following list:
Single input argument:
arg1 => { /* function body */ }
No input arguments:
( ) => { /* function body */ }
Single line function body:
( arg1, arg2, argn ) => /* single line */
Single expression broken over multiple lines:
( arg1, arg2, argn ) => ( /* multi line single expression */ )
Object literal return value:
( arg1, arg2, argn ) => ( { /* object literal */ } )