One of the most frequently asked JavaScript interview questions is:

What is this in JavaScript and how does it work?

Many developers memorize rules such as:

JAVASCRIPT
this === window;

or

JAVASCRIPT
arrow functions don't have this

but struggle when interviewers ask:

What determines the value of this?

The most important thing to understand is:

this is determined by how a function is called, not where it is defined.

What is this?#

this is a special keyword that refers to an object associated with the current execution context.

The value of this is decided at runtime.

Example:

JAVASCRIPT
const user = {
  name: "John",
  greet() {
    console.log(this.name);
  },
};

user.greet();

Output:

John

Here:

JAVASCRIPT
this === user;

because the function was called using:

JAVASCRIPT
user.greet();

Why Does JavaScript Need this?#

Imagine creating multiple objects:

JAVASCRIPT
const user1 = {
  name: "John",
};

const user2 = {
  name: "Sarah",
};

Without this, every method would need hardcoded references.

JAVASCRIPT
const user = {
  name: "John",
  greet() {
    console.log(user.name);
  },
};

This breaks when reused.

With this:

JAVASCRIPT
const user = {
  name: "John",
  greet() {
    console.log(this.name);
  },
};

The method becomes reusable for different objects.

3. Global Context & Function Invocation Rules#

In browsers:

JAVASCRIPT
console.log(this);

Output:

JAVASCRIPT
window;

Because the global execution context is the browser window.

Browser Example#

JAVASCRIPT
var name = "John";

console.log(this.name);

Output:

John

Equivalent to:

JAVASCRIPT
window.name;

Rule #2: Function Invocation#

Consider:

JAVASCRIPT
function greet() {
  console.log(this);
}

greet();

In non-strict mode:

JAVASCRIPT
window;

In strict mode:

JAVASCRIPT
undefined;

Strict Mode Example#

JAVASCRIPT
"use strict";

function greet() {
  console.log(this);
}

greet();

Output:

JAVASCRIPT
undefined;

This prevents accidental global object access.

4. Method Invocation Rule#

When a function is called as an object's method:

JAVASCRIPT
object.method();

this refers to that object.

Example:

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    console.log(this.name);
  },
};

user.greet();

Output:

John

Interview Trap#

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    console.log(this.name);
  },
};

const fn = user.greet;

fn();

Output:

undefined

(or window.name in non-strict mode)

Why?

Because:

JAVASCRIPT
fn();

is a normal function call.

The connection to user is lost.

5. Constructor Functions Rule#

When using new:

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

const user = new User("John");

JavaScript creates a new object and binds this to it.

Equivalent to:

JAVASCRIPT
const user = {};
user.name = "John";

Output:

JAVASCRIPT
{
  name: "John";
}

6. Arrow Functions & Lexical Binding#

Arrow functions do NOT create their own this.

Instead, they inherit this from the surrounding scope.

Example:

JAVASCRIPT
const user = {
  name: "John",

  greet: () => {
    console.log(this.name);
  },
};

user.greet();

Output:

undefined

Why?

Because the arrow function uses the surrounding this.

It does not receive:

JAVASCRIPT
this === user;

Normal Function vs Arrow Function#

Normal function:

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    console.log(this.name);
  },
};

Output:

John

Arrow function:

JAVASCRIPT
const user = {
  name: "John",

  greet: () => {
    console.log(this.name);
  },
};

Output:

undefined

Common React Example#

Bad:

JAVASCRIPT
class App {
  handleClick() {
    console.log(this);
  }
}

Passing directly:

JSX
<button onClick={this.handleClick}>

may lose context.

Historically developers used:

JAVASCRIPT
this.handleClick = this.handleClick.bind(this);

inside constructors.

Nested Functions Problem#

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    function inner() {
      console.log(this.name);
    }

    inner();
  },
};

user.greet();

Output:

undefined

Why?

Because:

JAVASCRIPT
inner();

is a normal function call.

Solution 1: Store Reference#

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    const self = this;

    function inner() {
      console.log(self.name);
    }

    inner();
  },
};

Output:

John

Solution 2: Arrow Function#

JAVASCRIPT
const user = {
  name: "John",

  greet() {
    const inner = () => {
      console.log(this.name);
    };

    inner();
  },
};

Output:

John

Arrow functions inherit the surrounding this.

7. Explicit Binding: call(), apply(), and bind()#

call() immediately invokes a function and sets this.

JAVASCRIPT
function greet() {
  console.log(this.name);
}

const user = {
  name: "John",
};

greet.call(user);

Output:

John

Explicit Binding with apply()#

Works like call() but arguments are passed as an array.

JAVASCRIPT
function greet(city) {
  console.log(this.name, city);
}

const user = {
  name: "John",
};

greet.apply(user, ["Delhi"]);

Output:

John Delhi

Explicit Binding with bind()#

Unlike call and apply:

JAVASCRIPT
bind();

does NOT execute immediately.

It returns a new function.

JAVASCRIPT
function greet() {
  console.log(this.name);
}

const user = {
  name: "John",
};

const boundFn = greet.bind(user);

boundFn();

Output:

John

call vs apply vs bind#

MethodExecutes ImmediatelyReturns Function
callYesNo
applyYesNo
bindNoYes

8. 'this' inside Event Handlers & Classes#

JAVASCRIPT
button.addEventListener("click", function () {
  console.log(this);
});

Output:

JAVASCRIPT
<button>

Inside event listeners:

JAVASCRIPT
this === element;

Event Handler with Arrow Function#

JAVASCRIPT
button.addEventListener("click", () => {
  console.log(this);
});

Output:

JAVASCRIPT
window;

(or outer scope)

Arrow functions do not get event-bound this.

Classes and this#

JAVASCRIPT
class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(this.name);
  }
}

const user = new User("John");

user.greet();

Output:

John

Here:

JAVASCRIPT
this === user;

9. Common Interview Q&A#

What Determines the Value of this?#

Not where the function is written.

Instead:

How the function is called

determines this.

Do Arrow Functions Have Their Own this?#

No.

They inherit this from the surrounding lexical scope.

Why Is bind() Useful?#

It permanently fixes the value of this.

JAVASCRIPT
const fn = greet.bind(user);

Useful when passing methods as callbacks.

Why Does React Use Arrow Functions Frequently?#

Arrow functions preserve lexical this.

This avoids losing context when functions are passed around.

Senior-Level Interview Answer#

The value of this in JavaScript is determined by how a function is invoked. In global scope, this usually refers to the global object. In object methods, it refers to the object before the dot. Constructor functions bind this to newly created instances via new. Functions can explicitly set this using call, apply, and bind. Arrow functions are different because they do not have their own this; instead they inherit it lexically from the surrounding scope. Understanding invocation patterns rather than memorizing rules is the key to mastering this.

Key Takeaways#

  • Dynamic Binding: The value of this is determined dynamically at runtime based on how a function is called, not where it is written.
  • Global Context: Points to window (or global in Node.js), resolving to undefined inside strict-mode execution.
  • Arrow Functions: Do not bind their own this; they inherit it lexically from their surrounding declaration context.
  • Explicit Binding: Use call(), apply(), or bind() to explicitly force a specific context object onto this.
  • Event Listeners: Inside event callbacks, this naturally points to the DOM element that received the event.