When to Use Arrow Functions vs Traditional Functions in JavaScript
This article explains the fundamental differences between arrow functions and traditional functions in JavaScript, shows five common scenarios where using a regular function is essential, and highlights the best situations to prefer arrow functions for concise, lexical this binding.
Since ES6, arrow functions ( ()=>{}) have become popular among JavaScript developers because of their concise syntax and lexical this binding.
However, arrow functions are not a silver bullet; they cannot fully replace the traditional function keyword. Overusing them, especially without understanding their behavior, can cause hard‑to‑track bugs because the handling of this differs fundamentally between arrow functions and regular functions.
Core differences quick memo:
function : the value of this is determined dynamically when the function is called, based on the caller.
=> (arrow function): it has no own this; it captures the this value from the surrounding lexical context, which remains fixed.
Understanding this explains why in the following five scenarios using function is either the best practice or the only correct choice.
Scenario 1: Object Methods
When defining a method on an object we usually want this to refer to the object itself so that its properties can be accessed.
❌ Wrong example (arrow function):
const person = {
name: '老王',
age: 30,
sayHi: () => {
// this comes from the global scope (window in browsers), not the person object
console.log(`大家好,我是 ${this.name}`);
}
};
person.sayHi(); // outputs: "大家好,我是 " (or undefined)In this example the arrow function sayHi captures the global this, so this.name is undefined.
✅ Correct approach (function):
const person = {
name: '老王',
age: 30,
sayHi: function() {
// this is dynamically bound to the person object when called
console.log(`大家好,我是 ${this.name}`);
},
// ES6 method shorthand, which is also a function
sayHiShorthand() {
console.log(`大家好,我是 ${this.name}`);
}
};
person.sayHi(); // "大家好,我是 老王"
person.sayHiShorthand(); // "大家好,我是 老王"Conclusion: When a method needs to reference the object’s own properties, use function or the ES6 method shorthand.
Scenario 2: DOM Event Listeners
When using addEventListener we often need to access the element that triggered the event. A regular function automatically binds this to that element.
❌ Wrong example (arrow function):
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
// this is still window or undefined, not the button element
this.classList.toggle('active'); // TypeError
});Here the arrow function captures the outer this, so the button cannot be accessed.
✅ Correct approach (function):
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
// this correctly refers to the button element
console.log(this); // <button id="myButton">...</button>
this.classList.toggle('active'); // works as expected
});Conclusion: In event‑handler callbacks, use function when you need this to refer to the event target.
Scenario 3: Constructor Functions
Arrow functions cannot be used as constructors. Calling an arrow function with new throws an error because they lack their own this and prototype properties.
❌ Wrong example (arrow function):
✅ Correct approach (function or class):
Conclusion: Never use an arrow function as a constructor; use a regular function or a class instead.
Scenario 4: Prototype Methods
When adding methods to a constructor’s prototype, we also want this to refer to the instance that calls the method.
❌ Wrong example (arrow function):
✅ Correct approach (function):
Conclusion: When defining methods on prototype, use function so that this points to the instance.
Scenario 5: Functions that Need arguments
Arrow functions do not have their own arguments object; they inherit it from the nearest non‑arrow function. If you need a true arguments object, a regular function is required.
❌ Wrong example (arrow function):
✅ Correct approach (function):
In modern JavaScript, rest parameters ( ...args) are preferred for variable‑arity functions, but when maintaining legacy code that relies on arguments, a regular function is the only viable choice.
When should you use arrow functions?
Arrow functions remain extremely useful, especially for their lexical this binding, which eliminates the need for patterns like var self = this or .bind(this).
Best use cases:
Callback functions : in array methods such as map, filter, forEach, or in setTimeout, Promise.then, when you need to preserve the outer this context.
const timer = {
seconds: 0,
start() {
setInterval(() => {
// this correctly refers to timer because the arrow function captures start's this
this.seconds++;
console.log(this.seconds);
}, 1000);
}
};
timer.start();Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaScript
Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
