Arrow functions are one of the handy features introduced in ES6. Using arrow functions correctly can make your code more concise and understandable. In this article, we will delve deeper into arrow functions in JavaScript, exploring how to use them and what to be cautious about. Arrow functions are defined as follows:
Arrow functions, also known as "fat arrow" functions from CoffeeScript (a transcompiled language), provide a more concise syntax for writing function expressions.
How to write arrow function in javascript
Basic Syntax with Multiple Parameters
// ES5
var multiEs5 = function(a, b) {
return a * b;
};
// ES6
const multiEs6 = (a, b) => { return a * b };
Basic Syntax with a Single Parameter
// ES5
var phraseSplitterEs5 = function phraseSplitter(phrase) {
return phrase.split(' ');
};
// ES6
const phraseSplitterEs6 = phrase => phrase.split(" ");
console.log(phraseSplitterEs6("Web Dev Genius")); // ["Web", "Dev", "Genius"]
Arrow functions shine when dealing with a single parameter, making the code concise and easy to understand.
No Parameters
// ES5
var docLogEs5 = function docLog() {
console.log(document);
};
// ES6
const docLogEs6 = () => { console.log(document); };
docLogEs6();
Object Literals
// ES5
var setNameIdsEs5 = function setNameIds(id, name) {
return {
id: id,
name: name
};
};
// ES6
const setNameIdsEs6 = (id, name) => ({ id: id, name: name });
console.log(setNameIdsEs6(1, "Hoa Nguyen")); // Object {id: 1, name: "Hoa Nguyen"}
Promises and Callbacks
// ES5
aAsync().then(function() {
return bAsync();
}).then(function() {
return cAsync();
}).done(function() {
finish();
});
// ES6
aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish());
Using arrow functions reduces the need for the function()
keyword, making the code more compact and readable.
Considerations When Using Arrow Functions
While arrow functions are concise and easy to understand, there are scenarios where they should not be used.
Click Handling
Consider a button element:
<button id="btnClickMe">Click me</button>
When someone clicks the button, you want to change its class to "on" and turn it yellow.
const button = document.querySelector('#btnClickMe');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
Using an arrow function in this case results in a TypeError because this
inside the arrow function refers to the global window
object, not the button. To solve this, use a regular function:
const button = document.querySelector('#btnClickMe');
button.addEventListener('click', function() {
console.log(this); // #btnClickMe Button element
this.classList.toggle('on');
});
Object Methods
Consider an object method:
const person = {
points: 100,
score: () => {
this.points++;
}
}
When an arrow function is used here, this
does not refer to the object person
but inherits from the parent scope, which is window
. To maintain the correct reference to this
, use a regular function:
const person = {
points: 100,
score: function() {
this.points++;
}
}
Prototype Methods
class Car {
constructor(make, colour) {
this.make = make;
this.colour = colour;
}
}
const beemer = new Car('BMW', 'blue');
const subie = new Car('Toyota', 'white');
Car.prototype.summarize = () => {
return `This car is a ${this.make} in the colour ${this.colour}`;
};
console.log(subie.summarize()); // This car is a undefined in the colour undefined
Using an arrow function for a prototype method results in undefined values for this.make
and this.colour
. To fix this, use a regular function:
Car.prototype.summarize = function() {
return `This car is a ${this.make} in the colour ${this.colour}`;
};
Conclusion
In conclusion, understanding when and how to use arrow functions in JavaScript is vital for writing clean, efficient, and bug-free code. Arrow functions provide a concise and elegant syntax, especially when dealing with simple operations or short-lived functions. They enhance readability and make the codebase more maintainable, improving developer productivity.
However, it is crucial to recognize their limitations, especially related to the binding of this
. Arrow functions do not bind their own this
context; instead, they inherit it from the parent scope, often resulting in unexpected behavior when used in certain contexts such as object methods, event handling, or prototype methods. In such cases, traditional functions should be preferred to ensure the correct binding of this
, preserving the expected behavior of the code.
Developers must be mindful of the specific scenarios where arrow functions are appropriate and where they are not. By understanding these nuances, developers can harness the power of arrow functions effectively, creating code that is both elegant and robust. As with any language feature, thoughtful consideration of its application is critical to harnessing its benefits while avoiding potential pitfalls and ensuring the creation of high-quality, maintainable JavaScript applications.