Skip to content
intermediate Phase 4 · JavaScript Fundamentals

this Keyword

Understand how this binding works in different execution contexts.

45m
0 problems
Topic Progress 0%

Global this

Global this

In the Browser

// Global scope
console.log(this); // Window object

// In strict mode
'use strict';
console.log(this); // undefined

In Node.js

// Global scope
console.log(this); // {}

// Module scope
console.log(module.exports); // {}

Function Calls

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

sayHello(); // Window (non-strict) or undefined (strict)

// Call/Apply/Bind
sayHello.call({ name: 'John' }); // { name: 'John' }

this in Different Contexts

Context this value
Global Window/undefined
Object method Object
Function Window/undefined
Arrow function Lexical scope
Class constructor Instance
Event handler Element

Strict Mode

// Non-strict: this is Window
function test() {
  console.log(this); // Window
}

// Strict: this is undefined
'use strict';
function test() {
  console.log(this); // undefined
}

Object Methods

Object Methods

Object Method this

const person = {
  name: 'John',
  greet() {
    console.log(`Hello, ${this.name}`); // "John"
  }
};

person.greet(); // this is person

this Depends on Call

const person = {
  name: 'John',
  greet() {
    console.log(this.name);
  }
};

const anotherPerson = { name: 'Jane' };

person.greet();          // "John"
anotherPerson.greet = person.greet;
anotherPerson.greet();   // "Jane"

const greet = person.greet;
greet();                 // undefined (global)

Method Extraction Problem

const person = {
  name: 'John',
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

const greet = person.greet;
greet(); // "Hello, undefined" (this is wrong!)

// Solutions:
// 1. Bind
const boundGreet = person.greet.bind(person);
boundGreet(); // "Hello, John"

// 2. Arrow function in method
const person = {
  name: 'John',
  greet: () => {
    console.log(`Hello, ${this.name}`); // this is NOT person!
  }
};

// 3. Store reference
const person = {
  name: 'John',
  init() {
    this.greet = () => {
      console.log(`Hello, ${this.name}`);
    };
  }
};

Nested Objects

const obj = {
  name: 'outer',
  nested: {
    name: 'inner',
    greet() {
      console.log(this.name); // "inner"
    }
  }
};

obj.nested.greet(); // "inner" (this is nested)

Method Chaining

const calculator = {
  value: 0,
  add(n) {
    this.value += n;
    return this; // Enable chaining
  },
  subtract(n) {
    this.value -= n;
    return this;
  },
  result() {
    return this.value;
  }
};

calculator.add(5).subtract(2).result(); // 3

Arrow Functions and this

Arrow Functions and this

Lexical this

Arrow functions don't have their own 'this' - they inherit from the enclosing scope.

const person = {
  name: 'John',
  greet: () => {
    // 'this' is NOT person!
    console.log(this.name); // undefined
  }
};

person.greet(); // undefined

When to Use Arrow Functions

// Good: callbacks
setTimeout(() => {
  console.log(this.name); // Correct 'this'
}, 1000);

// Good: array methods
const numbers = [1, 2, 3];
numbers.map(n => n * 2);

// Bad: object methods
const obj = {
  name: 'John',
  greet: () => {
    console.log(this.name); // undefined
  }
};

Object Method Workaround

// Use regular function for methods
const person = {
  name: 'John',
  greet() {
    console.log(this.name); // "John"
  }
};

// Or use arrow in property with function
const person = {
  name: 'John',
  greet: function() {
    console.log(this.name); // "John"
  }
};

// Or define in constructor
function Person(name) {
  this.name = name;
  this.greet = () => {
    console.log(this.name);
  };
}

Class Example

class Timer {
  constructor() {
    this.seconds = 0;
  }
  
  start() {
    // Arrow function inherits 'this' from class
    this.interval = setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
  
  stop() {
    clearInterval(this.interval);
  }
}

Event Handlers

// Arrow function: this is not the element
button.addEventListener('click', () => {
  console.log(this); // Window, not button!
});

// Regular function: this is the element
button.addEventListener('click', function() {
  console.log(this); // button
  this.classList.add('active');
});

Summary Table

Feature Regular Function Arrow Function
Has own this Yes No
this binding Dynamic (call site) Lexical (enclosing)
Use for methods Yes No
Use for callbacks Depends Yes

Quiz

1. What is 'this' in a regular function call?

Question 1 options

2. What is 'this' in an object method?

Question 2 options

3. What is 'this' in an arrow function?

Question 3 options

4. When should you use a regular function over an arrow function?

Question 4 options

5. What does .bind() do?

Question 5 options

Flashcards

Question

What is 'this' in an object method?

Answer

'this' refers to the object that owns the method.

Question

How do arrow functions handle 'this'?

Answer

They inherit 'this' from the enclosing scope (lexical this), not from the call site.

Question

What is the problem with extracting methods from objects?

Answer

The method loses its 'this' context. Use .bind() or arrow functions to fix.

Question

When should you NOT use arrow functions for methods?

Answer

When you need 'this' to refer to the object, like in object literals and prototypes.

Question

What does .bind() return?

Answer

A new function with 'this' permanently bound to the specified value.

Revision Notes

Key Takeaways

  • 1. 'this' depends on how a function is called, not where it's defined
  • 2. Object methods have 'this' pointing to the object
  • 3. Arrow functions inherit 'this' from enclosing scope
  • 4. Use .bind() to fix lost 'this' context
  • 5. Avoid arrow functions for object methods

Interview Tips

  • Explain how 'this' works in different contexts
  • Know the difference between regular and arrow functions
  • Understand method extraction and binding
  • Be able to fix 'this' issues in code

Cheat Sheet

this Keyword Cheat Sheet

this Values

Context this
Global Window/undefined
Object method Object
Regular function Window/undefined
Arrow function Lexical scope
Class constructor Instance
Event handler Element

Fixing this

// 1. Bind
const bound = method.bind(obj);

// 2. Arrow in constructor
function Person() {
  this.greet = () => this.name;
}

// 3. Store reference
const self = this;

Arrow vs Regular

// Arrow: lexical this
const obj = {
  greet: () => this.name // Not obj!
};

// Regular: own this
const obj = {
  greet() { return this.name; } // obj!
};