Skip to main content

Arrow methods vs regular methods

A regular class method is stored on the prototype and receives this dynamically, at call time, while an arrow method is an instance field that captures this when the object is created and never loses it. The syntactic difference is tiny, but the consequences for memory, inheritance and callback behaviour are radically different.

Theory

TL;DR

  • A regular method lives in Class.prototype and is shared by all instances.
  • An arrow method is an own property of the instance, a new function for every new.
  • A regular method resolves this at call time, an arrow method has it fixed forever.
  • An arrow method does not lose its context in setTimeout or addEventListener, a regular one does without bind.
  • super works only with regular methods; an arrow field has no access to it.
  • Arrow methods are enumerable and appear in Object.keys(), regular ones do not.

Quick example

javascript
class User { name = "Maria"; normal() { console.log("normal:", this.name); } arrow = () => { console.log("arrow:", this.name); }; } const u = new User(); setTimeout(u.normal, 500); // TypeError: Cannot read properties of undefined setTimeout(u.arrow, 500); // arrow: Maria

normal() lost its context because it was called as an ordinary function. arrow() kept the context because an arrow function has no this of its own, it captures this from the instance while the field is being initialised.

Syntax

A regular method:

javascript
class Button { handleClick() { console.log(this.label); } }

An arrow method (a method field):

javascript
class Button { handleClick = () => { console.log(this.label); }; }

At first sight the only difference is = () => {}, but the behaviour is fundamentally different.

The main difference: how this behaves

Method typeHow this works
Regular methodthis is decided at call time (dynamically)
Arrow methodthis is hard bound to the instance when the object is created

That is exactly why in the example above the regular method throws while the arrow one prints the name.

Where methods are stored

Method typeWhere it is storedShared by all instances?
RegularIn ClassName.prototypeYes
ArrowIn the instance itself (on every object)No
javascript
class A { normal() {} arrow = () => {}; } const a1 = new A(); const a2 = new A(); console.log(a1.normal === a2.normal); // true, one method on the prototype console.log(a1.arrow === a2.arrow); // false, each instance has its own

Arrow methods are recreated on every new A(). This gives this its independence, but costs a little in memory and in object creation speed.

Event handlers and callbacks

A regular method loses this unless you bind it by hand:

javascript
class Button { constructor() { this.label = "Click me"; document.body.addEventListener("click", this.handleClick); } handleClick() { console.log(this.label); // undefined, the context is lost } }

Solution 1: bind it manually.

javascript
document.body.addEventListener("click", this.handleClick.bind(this));

Solution 2 (more modern): use an arrow method.

javascript
class Button { label = "Click me"; handleClick = () => { console.log(this.label); // "Click me" }; }

Arrow methods fit React components and event handlers well, where it matters that this is not lost.

Inheritance and overriding

Regular methods are easy to override in subclasses, including through super:

javascript
class A { greet() { console.log("Hello from A"); } } class B extends A { greet() { super.greet(); // works console.log("Hello from B"); } }

With an arrow field this does not work:

javascript
class A { greet = () => console.log("Hello from A"); } class B extends A { greet = () => { super.greet(); // error, there is no super method to call }; }

The reason is that arrow methods are created on the instance, not on the prototype, so overriding is just overwriting a field, and the parent version simply is not in the prototype chain.

Difference in iteration and debugging

Regular methods are non-enumerable, so Object.keys() does not show them. Arrow methods are ordinary instance properties, so they are enumerable:

javascript
class Example { method() {} arrow = () => {}; } const e = new Example(); console.log(Object.keys(e)); // ['arrow']

This also means arrow fields are copied by spread and Object.assign, while prototype methods are not.

Performance

CriterionRegular methodArrow method
Memory1 function for allits own function per instance
Creation speedFasterSlower
this contextLost without bindAlways preserved
Suitable for superYesNo
Suitable for callbacksNeeds bindAn ideal fit

Summary comparison

FeatureRegular methodArrow method
Where it is storedClass.prototypeIn the instance
Shared by allYesNo
this behaviourDepends on the callFixed
this lost in callbacksPossibleNo
super supportYesNo
Takes part in inheritanceYesNo
PerformanceBetterSlightly worse
Use in React and eventsInconvenientVery convenient

In short: use regular methods when the method is logically shared by all instances and may be overridden; use arrow methods when preserving this matters, for example when passing the method as a callback or an event handler.

Common mistakes

  • Making every method an arrow just in case. That multiplies functions in memory and strips the class of normal inheritance.
  • Expecting super inside an arrow field. It is not there, because the field does not live on the prototype.
  • Being surprised that Object.keys(instance) shows methods. It shows the arrow fields, because they are enumerable own properties.
  • Assuming a regular method will keep this on its own. Without bind or an arrow wrapper it loses the context in any callback.
  • Confusing the initialisation order. Arrow fields are created while the instance is being constructed, so in a base class they are not yet available at the time its constructor runs in a subclass.
  • Using arrow fields where the method must be mocked or replaced in tests through the prototype. Patching Class.prototype.method has no effect on an arrow field.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.