What About These Fat Arrow Functions?
Donny
Posted on October 16, 2020
When I first started learning JavaScript a couple years ago, I was taught to write the classic arrow expressions:
function myMessage( ) {
console.log(“Hello, World!”)
}
Then I started using the new-fangled arrow function ES2015 way of
writing the same thing:
const myMessage = ( ) => {
console.log(“Hello, World!”)
}
The new syntax seems cool to me, but then I found out there were some important differences between the new and the old syntax. Sometimes those differences made arrow functions really amazing and other times, they caused unforeseen problems.
First, let’s go over some basics:
Omitting Parentheses.
Normally, we use parentheses to define the parameters our arrow function:
const addTwoNumbers = ( x, y ) => {
return x + y
}
Above, we’ve put parentheses around our two parameters, x and y.
We also must use parentheses if we have zero parameters:
const mySecretMessage = ( ) => {
console.log(“This is fun”)
}
However, if we have just one parameter, we can optionally omit the parenthesis:
const sayMyName = (string) => {
console.log (string)
}
// we could have eliminated the parenthesis since there
// is only one parameter in our arrow function.
// Let’s rewrite it:
const sayMyName = string => {
console.log (string)
}
To summarize: you can only omit parentheses around the parameters of an arrow function if you have one parameter. If you have zero, two, three or more parameters, you must use parentheses.
Omit the Curly Braces
When we have just one statement in our function body, we can simplify the statement by vomiting the curly braces:
This function with only one statement in the function body:
//Example A
const addTwoNumbers = ( x, y ) => {
return x + y
}
Becomes this:
//Example B
const addTwoNumbers = ( x, y ) => return x + y
}
Cool! In the re-written statement, we 1) removed the curly braces, 2) removed the keyword “return” and 3) put the function body statement on the same line as the function definition.
Note the use of a couple of new vocabulary words. in Example A above, when we use the return keyword it is known as an explicit return. In contract, when we omit the return keyword as in Example B, it is called an implicit return.
***An Outlier Occassion Where Parentheses Are A Must:
If you’re going to return an object literal, then you must wrap that object in parentheses:
const greetings = name =>({ message: `Hello, ${ name }!`})
//now call “greetings”
greetings(‘Timmy’) // -> { message: Hello, Timmy! }
If we don’t wrap the object literal in parentheses, then JavaScript will confuse the curly braces with those that define the function body.
The Famous “This”
The “this” keyword is a well-known bugaboo for many a JavaScript programmer. And to make it more fun, the “this” keyword acts differently in a classic function call vs. an arrow function call.
Let’s look at how “this” works in a method of an object.
See the method below:
const car = {
model: 'Fiesta',
manufacturer: 'Ford',
fullName: function() {
return `${this.manufacturer} ${this.model}`
}
}
Above you see the object “car”. Look at the key “fullName”. The value corresponding to “fullName” is a classic anonymous function.
In this case, when we call the fullName function like this:
car.fullName( )
because we’re using a classic function, JavaScript knows to look for the meaning of “this” in the object it’s being called in. In our case, the “this” is being called in the object named “car”. Good, now JS will know how to parse the literals “this.manufacturer” and “this.model”. We just said the “this” must refer to the “car” object, so we we have “manufacturer” and a “model” property in our “car” object? Yes, we do! So JS can return:
car.fullName( ) // returns: “Ford Fiesta”
Now let see what would happen if we turn our car.fullName method into an arrow function like this:
const car = {
model: 'Fiesta',
manufacturer: 'Ford',
fullName: () => {
return `${this.manufacturer} ${this.model}`
}
}
What happens now when we try to call “car.fullName( )” ?
The difference lies in the fact how the arrow function will interpret the “this” keyword. We already saw how the classic function knew that “this” referred to the object itself and therefore all the object’s key/value pairs were made available to that function.
However, our arrow function interprets the “this” keyword differently.
Our arrow function will only look for a meaning of “this” in its lexical scope meaning the context where that function is executed.
In other words, this is the only thing our arrow function “sees”:
fullName: ( ) => {
return `${ this.manufacturer} ${ this.model }`
Our arrow function only sees the parts of the object that directly concern its own execution. It does not see the “model” property nor does it see the “manufacturer” property.
Therefore, when our fat arrow method function tries to interpret “this.manufacturer” and “this.model” it finds no references to anything like that. Both values will be returned as undefined.
car.fullName( ) // “undefined undefined”
The upshot of all “this” is: when constructing a method in an object, you have to use the classic function keyword.
Posted on October 16, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.