The 'this' Keyword in JavaScript

The 'this' keyword in JavaScript refers to the current execution context. Its value depends on how and where a function is called, not where it's defined.

Global Context

// In global scope
console.log(this === window); // true (in browser)

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

// In modules
console.log(this === undefined); // true (modules are strict by default)

Object Methods

// Regular object method
const user = {
  name: 'John',
  greet() {
    return `Hello, I'm ${this.name}`;
  }
};

console.log(user.greet()); // "Hello, I'm John"

// Losing context
const greet = user.greet;
console.log(greet()); // "Hello, I'm undefined"

// Fixing with bind
const boundGreet = user.greet.bind(user);
console.log(boundGreet()); // "Hello, I'm John"

Constructor Functions

// Constructor function
function User(name) {
  this.name = name;
  this.sayHi = function() {
    return `Hi, ${this.name}`;
  };
}

const user = new User('John');
console.log(user.sayHi()); // "Hi, John"

// Without new keyword
const user2 = User('John'); // this refers to window/global
console.log(user2); // undefined
console.log(window.name); // "John" (in non-strict mode)

Arrow Functions

// Arrow functions inherit 'this'
const obj = {
  name: 'Object',
  regularMethod() {
    return () => {
      return this.name;
    };
  },
  arrowMethod: () => {
    return this.name;
  }
};

const method = obj.regularMethod();
console.log(method()); // "Object"

console.log(obj.arrowMethod()); // undefined (this refers to outer scope)

Event Handlers

class Button {
  constructor(text) {
    this.text = text;
    this.element = document.createElement('button');
    
    // Wrong way - loses context
    this.element.addEventListener('click', function() {
      console.log(this.text); // undefined
    });
    
    // Correct ways
    this.element.addEventListener('click', (e) => {
      console.log(this.text); // works
    });
    
    this.element.addEventListener('click', this.handleClick.bind(this));
  }
  
  handleClick() {
    console.log(this.text);
  }
}

Call, Apply, and Bind

function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`;
}

const person = { name: 'John' };

// Using call
console.log(greet.call(person, 'Hello', '!')); // "Hello, John!"

// Using apply
console.log(greet.apply(person, ['Hi', '?'])); // "Hi, John?"

// Using bind
const boundGreet = greet.bind(person);
console.log(boundGreet('Hey', '.')); // "Hey, John."

Common Interview Follow-up Questions

  1. How does 'this' behave differently in arrow functions?
  2. What's the difference between call, apply, and bind?
  3. How does 'this' work in event handlers?
  4. What happens when you forget the 'new' keyword?

Best Practices

  • Use arrow functions for callbacks to preserve 'this'
  • Be careful with standalone function calls
  • Always use 'new' with constructor functions
  • Consider using class syntax for clearer 'this' binding
  • Use bind/arrow functions for event handlers