Arrow Functions & Lexical This
Introduced in ES6, arrow functions offer a concise syntax for writing function expressions and solve historical confusion surrounding the this keyword.
1. Arrow Function Syntax
Arrow functions are defined using the "fat arrow" operator (=>):
// Regular Function Expression
const square = function(x) {
return x * x;
};
// Arrow Function
const squareArrow = (x) => {
return x * x;
};Syntax Simplifications:
- Single Parameter: You can omit the parentheses around the parameter list.
const double = x => { return x * 2; };- Implicit Return: If the function body contains only a single expression, you can omit the curly braces
{}and thereturnkeyword.
const multiply = (a, b) => a * b; // Implicitly returns a * b- Returning Objects: To implicitly return an object literal, wrap it in parentheses to prevent the engine from misinterpreting it as function brackets:
const getUser = id => ({ id: id, role: "Guest" });2. Dynamic vs. Lexical this
The biggest functional difference between regular functions and arrow functions is how they handle the this keyword.
A. Regular Functions: Dynamic this
In a regular function, this is dynamic. Its value depends entirely on how the function is called:
- Called as a method of an object:
thispoints to that object. - Called as a standalone function:
thispoints towindow(orundefinedin strict mode).
const user = {
name: "Alice",
greet: function() {
console.log(`Hello, I am ${this.name}`);
// Callback function inside:
setTimeout(function() {
// Called standalone by timer, this points to window!
console.log(`My name is still ${this.name}`);
}, 100);
}
};
user.greet();
// Output:
// "Hello, I am Alice"
// "My name is still undefined" (window.name is undefined)B. Arrow Functions: Lexical this
Arrow functions do not have their own this binding. Instead, they inherit this lexically from their enclosing scope.
const userCorrected = {
name: "Alice",
greet: function() {
console.log(`Hello, I am ${this.name}`);
// Arrow function inherits 'this' from greet():
setTimeout(() => {
console.log(`My name is still ${this.name}`);
}, 100);
}
};
userCorrected.greet();
// Output:
// "Hello, I am Alice"
// "My name is still Alice"3. When NOT to Use Arrow Functions
Because arrow functions do not bind their own this, you should avoid using them in:
- Object Methods: If you use an arrow function as an object method,
thiswill point to the outer scope (e.g.window), not the object itself. - Event Listeners: In DOM event handlers, a regular function binds
thisto the element that triggered the event. An arrow function will bind it to the surrounding lexical scope (typicallywindow).
const btn = document.querySelector('button');
// AVOID:
btn.addEventListener('click', () => {
this.classList.add('active'); // Error: cannot read property of undefined
});In the next guide, we will explore variables scopes, context hoisting, and closures.
Published on Last updated: