How do arrow functions differ from regular functions?

Beginner8 min interview
Skills tested:
Lexical this bindingarguments object behaviorConstructor usage restrictionsImplicit return syntaxPrototype chain absence in arrow functions

Advertisement

🧩 Scenario

In a real codebase, you will encounter this distinction most often when writing class methods, event listeners, and array callbacks. A common bug arises when a developer uses a regular function inside a class method as a callback, only to find that this is undefined or refers to the wrong object. Understanding which function type captures this from the surrounding scope versus which one creates its own binding is the difference between a five-minute fix and a two-hour debugging session.

Architecture Walkthrough

Lexical vs Dynamic this Binding

Regular functions create their own this binding at call time. The value of this depends on how the function is called, not where it is defined. A method called as a standalone function loses its original context, which is a frequent source of bugs when passing methods as callbacks.

Arrow functions do not create a this binding at all. They inherit this from the enclosing lexical scope at the time they are defined. This makes them predictable in asynchronous callbacks and class methods, because this will always refer to the object you expect.

Missing arguments, prototype, and new

Arrow functions do not have an arguments object. If you need to collect variadic arguments inside an arrow function, you must use rest parameters (...args). This is actually the preferred approach in modern JavaScript anyway, but it catches developers off guard when they expect arguments to exist.

Arrow functions also have no prototype property, which means they cannot be used with the new keyword. Attempting to call new on an arrow function throws a TypeError immediately. This is by design: because arrow functions have no this of their own, constructing an object around them would have no meaning.

When to Prefer a Regular Function

Arrow functions are not universally better. Object literals that use arrow functions for methods will have a broken this, since the surrounding lexical scope at definition time is the outer scope, not the object itself. DOM event handlers that need this to refer to the element that fired the event must use regular functions. Generator functions that use yield cannot be arrow functions at all.

Choosing between the two comes down to one question: do you need a new this binding, or do you want to capture the one you already have?


Key Code Explained

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

  start() {
    // Regular function: this is undefined in strict mode inside the callback
    setInterval(function () {
      this.count++; // TypeError: Cannot set properties of undefined
    }, 1000);
  }

  startFixed() {
    // Arrow function: this is captured from startFixed's scope (the Timer instance)
    setInterval(() => {
      this.count++;
      console.log(this.count);
    }, 1000);
  }
}

The start method breaks because setInterval calls its callback as a plain function, not as a method of Timer. The regular function creates a new this binding that has no connection to the Timer instance.

The startFixed method works because the arrow function does not create a this binding. It looks up the scope chain and finds the this from startFixed, which is the Timer instance. This is what "lexical this" means in practice.

// arguments is not available in arrow functions
const regular = function () {
  console.log(arguments[0]); // works
};

const arrow = (...args) => {
  console.log(args[0]); // correct approach for arrow functions
};

Tradeoffs

ApproachProCon
Arrow function for callbacksPredictable this from surrounding scopeCannot be used as constructors or generators
Regular function for methodsCreates its own this, useful for object methodsRequires .bind(this) or a stored reference when used as callbacks
Regular function with .bind(this)Explicit and readable in some codebasesVerbose and creates a new function on every call if done inside render

What Interviewers Actually Check

  • Whether you know that this in an arrow function is determined at definition time, not call time
  • Whether you can name at least two things arrow functions lack (arguments, prototype, new support)
  • Whether you understand that arrow functions are not always the better choice
  • Whether you can trace what this refers to in a nested callback scenario
  • Whether you know the implicit return shorthand and when it applies
  • Whether you can identify the bug in an arrow function used as an object method

Follow-Up Questions

  1. How does this behave inside an arrow function defined inside a class field, compared to one defined inside a constructor method?
  2. What happens if you nest an arrow function inside another arrow function? What does this resolve to?
  3. How would you test that a callback correctly maintains the expected this binding?
  4. In a high-frequency event handler that runs thousands of times per second, does the choice of function type have any performance impact?
  5. A PM asks why a submitted form event listener is not updating the component state. You find the handler is an arrow function on a plain object. How do you explain and fix it?

Common Candidate Mistakes

  • Using an arrow function as an object method and being confused when this refers to the outer scope instead of the object
  • Trying to call new on an arrow function and not knowing why it throws
  • Assuming arguments is available inside an arrow function
  • Returning an object literal from a single-expression arrow function without wrapping it in parentheses: () => { foo: 1 } is a block with a label, not an object
  • Thinking .bind() or .call() can override this inside an arrow function (they cannot)

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you explain what lexical this means and why it matters in callbacks?
  • Can you demonstrate the difference in this behavior inside setTimeout using both function types?
  • Can you explain why arrow functions cannot be used as constructors?
  • Can you describe the missing arguments object and how to work around it with rest parameters?
  • Can you identify at least two situations where a regular function is the correct choice over an arrow function?

Summary

Arrow functions and regular functions are not interchangeable. The most important distinction is this binding: regular functions create a new binding at call time, while arrow functions inherit this from the scope where they were defined. This makes arrow functions reliable for callbacks and class methods, but unreliable for object method definitions and DOM event handlers that need this to reference the element.

Beyond this, arrow functions also lack arguments, prototype, and the ability to be called with new. These restrictions are intentional. Arrow functions are designed to be lightweight, lexically transparent function expressions, not full replacements for the function declaration.

When choosing between the two, ask whether the code needs to create a new execution context or borrow one from its surroundings. That single question covers the vast majority of real-world decisions between arrow and regular functions.

Related Videos
Watch these videos to learn more about this topic
Frequently Asked Questions

Can arrow functions be used as constructors?

No. Arrow functions don't have their own this or prototype, so they can't be used as constructors.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement