Arrow Functions vs. Regular Functions: Understanding the Difference
In a recent interview, I was asked if I was familiar with ES5, ES6, and ES7 in JavaScript. I answered “yes” and gave the example of the different ways to write functions (eg., the introduction of arrow functions with ES6). That led the interviewer to ask one simple follow-up question: What’s the difference between arrow functions and normal functions?
Off the bat, I could describe the syntactical differences, but that’s not what my interviewer was looking for. So, I decided to go back over JavaScript fundamentals to reacquaint myself with the many answers to that question.
Hoisting
(for normal functions)
Normal functions are hoisted when they’re written with a function declaration.
//Function declarationfunction run(num) {
return `I will run for ${num} miles.`
}
Normal functions are not hoisted when they’re written as an expression.
//Function expressionconst run = function(num) {
return `I will run for ${num} miles.`
}
Hoisting
(for arrow functions)
So since arrow functions, by default, are written as an expression, they’re also not hoisted.
//Arrow function (by default, an expression)const run = num => {
return `I will run for ${num} miles.`
}
In sum:
Hoisted
- normal functions that use a function declaration
NOT Hoisted
- normal functions written as an expression
- arrow functions
Wait… What’s Hoisting Again?
Recall that variable and function declarations are put into memory during the compile phase, so they’re thought of as being “hoisted” (though, not literally) to the top of your code. That gives you the ability to invoke a function before you declare it.
run(6) //Invoked function here before declaring it.function run(num) {
return `I will run for ${num} miles.`
}
“this” Keyword
(for normal functions)
The value of this
inside of a normal function is dynamic, meaning it depends on how the function is invoked. Using a simple invocation will log the global object (window).
function run() {
console.log(this);
}
// Simple invocation
run() // logs global object (window)
If you invoke a method using this
inside of an object, the value of this
will be equal to the object enclosing the method.
const exercise = {
run() {
console.log(this);
}
}// Method invocation
exercise.run() // logs exercise
“this” Keyword
(for arrow functions)
Unlike normal functions, arrow functions’ this
value will always be bound to the value of the outer function/non-arrow function. That’s because arrow functions don’t define their own execution context.
const exercise = {
run() {
console.log(this) // logs exercise
const callback = () => {
console.log(this) // logs exercise
}
}
}
exercise.run()
Those are 2 ways to distinguish regular functions from arrow functions and when to use them. There are still many differences to explore, which I look forward to learning.
References: