Arrow functions vs regular functions in JavaScript

HighIntermediateJavascript
Quick Answer

Arrow and regular functions look similar but behave differently for this binding, constructors, arguments, and method design. Strong answers explain lexical vs dynamic this, prototype/new behavior, and when each style is safer in real frontend code.

Answer

Direct answer

Use arrow functions for short callbacks and lexical this. Use regular functions when you need dynamic this, constructor behavior, or function-level features like arguments and prototype.

The interview goal is not 'which is better', but which fits the behavior you need.

Behavior

Regular function

Arrow function

this

Dynamic (depends on call-site)

Lexical (captured from outer scope)

arguments

Own arguments object

No own arguments (use rest)

Constructor with new

Supported

Not supported

prototype property

Exists

Does not exist

call/apply/bind for this

Can rebind this

Cannot change lexical this

Same purpose (callable code), different runtime semantics.

this is the biggest practical difference

Regular functions take this from how they are invoked. Arrows capture this from where they are defined. That is why arrows are common in async callbacks tied to class/object context.

JAVASCRIPT
class Counter {
  constructor() {
    this.count = 0;
  }

  tickWithArrow() {
    setTimeout(() => {
      this.count++;
      console.log(this.count);
    }, 0);
  }

  tickWithRegular() {
    setTimeout(function () {
      // this is not Counter instance here
      // in strict mode it is undefined
      console.log(this);
    }, 0);
  }
}
                  

Constructors and prototypes

If you need new or prototype-based instance methods, use regular functions (or class). Arrow functions cannot be constructors and have no prototype.

JAVASCRIPT
function User(name) {
  this.name = name;
}

const create = (name) => ({ name });

const u1 = new User('Ada'); // ✅
// const u2 = new create('Ada');
// TypeError: create is not a constructor
                  

arguments and rest parameters

Regular functions expose arguments. Arrows do not. Modern code usually prefers explicit rest parameters because they are clearer and type-friendly.

JAVASCRIPT
function regular() {
  return arguments.length;
}

const arrow = (...args) => args.length;

console.log(regular(1, 2, 3)); // 3
console.log(arrow(1, 2, 3));   // 3
                  

Method-definition pitfall

Putting arrow functions directly as object methods can surprise you when you expect dynamic receiver-based this. Regular method syntax is usually the right choice for object behavior.

JAVASCRIPT
const account = {
  balance: 100,
  regularMethod() {
    return this.balance;
  },
  arrowMethod: () => {
    return this?.balance; // lexical this, not account receiver
  }
};

console.log(account.regularMethod()); // 100
console.log(account.arrowMethod());   // usually undefined
                  

Performance and architecture nuance

In classes, prototype methods (regular method syntax) are shared across instances. Arrow methods defined as class fields create a function per instance. Sometimes this is worth it for stable lexical this, but it can increase memory usage in large object graphs.

Use case

Prefer

Reason

Array transforms/callbacks

Arrow

Short syntax and lexical this is often ideal.

Object/class behavior methods

Regular method

Receiver-based dynamic this and prototype sharing.

Constructor/factory with new

Regular function/class

Arrows cannot be constructed.

Need parameter list as array

Either + rest params

Rest is clearer than relying on arguments.

Decide by runtime semantics, not style preference alone.

Interview one-liner

Arrow functions are best for lexical-context callbacks; regular functions are best when call-site this, constructors, or prototype-based behavior matter.

Practical scenario
A UI class passes a method as an event callback. With a regular function callback, this drifts and state updates fail; with an arrow callback (or explicit bind), the handler keeps instance context.

Common pitfalls

      • Using arrow methods where dynamic receiver behavior is needed.
      • Using regular callbacks without binding and losing this.
      • Overusing class-field arrows and increasing per-instance memory.
Trade-off or test tip
Test handlers both as direct calls and detached callbacks to verify context behavior before shipping.

Still so complicated?

Think of regular functions as drivers who take directions from the current caller, while arrow functions always follow the route from where they were created.

Summary

Both function types are essential. Bugs happen when we choose by syntax convenience instead of semantics. If context ownership matters, verify this behavior explicitly and test detached-callback scenarios.

Similar questions
Guides
Preparing for interviews?

Use the relevant interview-question hub first, then move into a concrete study plan before targeted company sets.