JavaScript Interview Prep
ES6+ Features

Arrow Functions

Lexical this and Shorter Syntax

LinkedIn Hook

You're writing a React component. Inside setInterval, you type function() { this.count++ } — and suddenly this is undefined.

You switch to an arrow function: () => { this.count++ } — and it just works.

Magic? No. Arrow functions don't have their own this. They borrow it from the enclosing lexical scope, permanently, at the moment they're defined.

But that same feature becomes a bug the second you use an arrow as an object method, a prototype method, or an event handler where you need this to be the element.

In this lesson you'll learn all four "no own" rules of arrow functions — no this, no arguments, no prototype, no new — and exactly when a regular function is the right answer.

If you've ever fixed a bug by turning => into function (or vice versa) without really knowing why — this lesson fixes that forever.

Read the full lesson -> [link]

#JavaScript #InterviewPrep #ES6 #ArrowFunctions #This #Frontend #CodingInterview


Arrow Functions thumbnail


What You'll Learn

  • All the syntax variations — implicit return, single-param shortcut, returning object literals
  • Why arrow functions have lexical this (and no arguments, no prototype, no new)
  • The four classic "do not use arrow" situations: methods, constructors, prototypes, dynamic event handlers

Why Arrows Are More Than Shorter Syntax

Arrow functions are the most visible ES6 change, but their real significance isn't the shorter syntax — it's how they handle this. Think of an arrow function as a camera that permanently records the scene it was created in. No matter where you play the recording later, the scene never changes.

Syntax Variations

// Full body
const add = (a, b) => {
  return a + b;
};

// Implicit return (single expression)
const add2 = (a, b) => a + b;

// Single parameter — parentheses optional
const double = x => x * 2;

// No parameters — parentheses required
const greet = () => "Hello!";

// Returning an object — wrap in parentheses
const makeUser = (name, age) => ({ name, age });

// With array methods
const evens = [1, 2, 3, 4, 5].filter(n => n % 2 === 0);
const doubled = [1, 2, 3].map(n => n * 2);

No Own this — Lexical this

Arrow functions don't have their own this. They capture this from the enclosing lexical scope at the time they're defined.

function Timer() {
  this.seconds = 0;

  // Arrow function captures 'this' from Timer
  setInterval(() => {
    this.seconds++;
    console.log(this.seconds);
  }, 1000);
}

const t = new Timer(); // Works! 'this' refers to the Timer instance

// Compare with regular function (broken)
function BrokenTimer() {
  this.seconds = 0;

  setInterval(function() {
    this.seconds++; // 'this' is window/undefined, NOT BrokenTimer
    console.log(this.seconds); // NaN
  }, 1000);
}

No Own arguments Object

function outer() {
  // Arrow inherits 'arguments' from outer
  const inner = () => {
    console.log(arguments); // outer's arguments: [1, 2, 3]
  };
  inner();
}
outer(1, 2, 3);

// Use rest parameters instead
const sum = (...args) => args.reduce((a, b) => a + b, 0);
sum(1, 2, 3); // 6

When NOT to Use Arrow Functions

// 1. Object methods — arrow captures wrong 'this'
const person = {
  name: "Rakibul",
  greet: () => {
    console.log(this.name); // undefined — 'this' is global, not person
  }
};

// Fix: use shorthand method
const personFixed = {
  name: "Rakibul",
  greet() {
    console.log(this.name); // "Rakibul"
  }
};

// 2. Constructors — arrow functions can't be used with 'new'
const Foo = () => {};
// new Foo(); // TypeError: Foo is not a constructor

// 3. Dynamic this (event handlers)
button.addEventListener("click", () => {
  console.log(this); // window, NOT the button
});

button.addEventListener("click", function() {
  console.log(this); // the button element
});

// 4. Prototype methods
function Person(name) {
  this.name = name;
}
Person.prototype.greet = () => {
  console.log(this.name); // undefined
};
// Fix: use regular function
Person.prototype.greet = function() {
  console.log(this.name);
};

Arrow Functions visual 1


Common Mistakes

  • Writing object methods as arrow functions and wondering why this is undefined or window — the arrow captured the module/global this, not the object. Use the shorthand method syntax greet() { ... } for methods.
  • Using an arrow function as a constructor — new Foo() throws a TypeError because arrows have no [[Construct]] internal slot and no prototype property.
  • Thinking .call(...) or .bind(...) can "rebind" an arrow's this. It can't. The arguments go through, but the this passed in is silently ignored — arrows are permanently glued to their lexical scope.

Interview Questions

Q: What are the key differences between arrow functions and regular functions?

Arrow functions: (1) no own this — use lexical this, (2) no arguments object, (3) can't be used as constructors with new, (4) no prototype property, (5) can't be used as generators. Use rest params (...args) instead of arguments.

Q: When should you NOT use arrow functions?

Don't use them as: object methods (wrong this), constructors (throws error), prototype methods (wrong this), event handlers where you need this to be the element, and functions that need their own arguments object.

Q: Can you use call, apply, or bind on arrow functions?

You can call them, but they have no effect on this. Arrow functions always use the this from their enclosing scope, regardless of how they're invoked. The methods still work for passing arguments, though.

Q: Can arrow functions be used as constructors?

No. new Foo() where Foo is an arrow throws TypeError: Foo is not a constructor. Arrows have no [[Construct]] slot and no prototype property, so they can never produce a new instance.


Quick Reference — Cheat Sheet

ARROW FUNCTIONS — QUICK MAP

Syntax:
  (a, b) => a + b              -> implicit return
  x => x * 2                   -> single param, no parens
  () => "hi"                   -> no params, parens required
  () => ({ key: val })          -> return object literal (wrap!)
  (a, b) => { return a + b; }  -> block body, explicit return

No own (inherited from lexical parent):
  - this
  - arguments
  - super
  - new.target

Not usable as:
  - constructor (no `new`)
  - generator   (no `function*` arrow)
  - dynamic-this method

Prefer arrows for:
  - array callbacks (map/filter/reduce)
  - setTimeout/setInterval in classes
  - promise .then chains
  - short pure-expression helpers

Previous: Template Literals -> Backticks and Tagged Templates Next: Default Parameters -> Clean Defaults Without Falsy Traps


This is Lesson 9.2 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.

On this page