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
thisbinding.
However, arrow functions are not a silver bullet; they cannot fully replace the traditional
functionkeyword. Overusing them, especially without understanding their behavior, can cause hard‑to‑track bugs because the handling of
thisdiffers fundamentally between arrow functions and regular functions.
Core differences quick memo:
function : the value of
thisis determined dynamically when the function is called, based on the caller.
=> (arrow function): it has no own
this; it captures the
thisvalue from the surrounding lexical context, which remains fixed.
Understanding this explains why in the following five scenarios using
functionis either the best practice or the only correct choice.
Scenario 1: Object Methods
When defining a method on an object we usually want
thisto refer to the object itself so that its properties can be accessed.
❌ Wrong example (arrow function):
<code>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)
</code>In this example the arrow function
sayHicaptures the global
this, so
this.nameis undefined.
✅ Correct approach (function):
<code>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(); // "大家好,我是 老王"
</code>Conclusion: When a method needs to reference the object’s own properties, use
functionor the ES6 method shorthand.
Scenario 2: DOM Event Listeners
When using
addEventListenerwe often need to access the element that triggered the event. A regular
functionautomatically binds
thisto that element.
❌ Wrong example (arrow function):
<code>const button = document.getElementById('myButton');
button.addEventListener('click', () => {
// this is still window or undefined, not the button element
this.classList.toggle('active'); // TypeError
});
</code>Here the arrow function captures the outer
this, so the button cannot be accessed.
✅ Correct approach (function):
<code>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
});
</code>Conclusion: In event‑handler callbacks, use
functionwhen you need
thisto refer to the event target.
Scenario 3: Constructor Functions
Arrow functions cannot be used as constructors. Calling an arrow function with
newthrows an error because they lack their own
thisand
prototypeproperties.
❌ Wrong example (arrow function):
✅ Correct approach (function or class):
Conclusion: Never use an arrow function as a constructor; use a regular
functionor a
classinstead.
Scenario 4: Prototype Methods
When adding methods to a constructor’s
prototype, we also want
thisto refer to the instance that calls the method.
❌ Wrong example (arrow function):
✅ Correct approach (function):
Conclusion: When defining methods on
prototype, use
functionso that
thispoints to the instance.
Scenario 5: Functions that Need arguments
Arrow functions do not have their own
argumentsobject; they inherit it from the nearest non‑arrow function. If you need a true
argumentsobject, 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
functionis the only viable choice.
When should you use arrow functions?
Arrow functions remain extremely useful, especially for their lexical
thisbinding, which eliminates the need for patterns like
var self = thisor
.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
thiscontext.
<code>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();
</code>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.