Toggle theme D

The word this confuses a lot of JavaScript developers. In other languages, it's usually straightforward — this refers to the current object. In JavaScript, it depends on how the function is called, and that changes everything.

What this Actually Means

Think of this as asking the question "who is calling this function?" The answer changes based on context. When you understand that this is determined by the call site, not the function definition, things start making more sense.

function greet() {
  console.log('Hello, ' + this.name);
}

const alice = { name: 'Alice' };
const bob = { name: 'Bob' };

greet.call(alice);  // 'Hello, Alice'
greet.call(bob);    // 'Hello, Bob'

Same function, different this — because the caller changes.

this in Normal Functions

When a function is called in the regular way (not as a method), this depends on the context:

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

showThis();        // Window (or undefined in strict mode)

const obj = {
  name: 'Test',
  showThis: showThis
};

obj.showThis();    // { name: 'Test', showThis: function... }

Plain function calls set this to the global object (or undefined in strict mode). Method calls set this to the object the method belongs to.

this in Objects

Here's where it clicks for most people:

const person = {
  name: 'Charlie',
  greet: function() {
    return 'Hi, I am ' + this.name;
  }
};

console.log(person.greet());  // 'Hi, I am Charlie'

When you call person.greet(), this refers to person. Easy. But watch what happens when you extract the method:

const greet = person.greet;
console.log(greet());  // 'Hi, I am ' + undefined (or error)

Now it's called without an object context, so this is lost. This is the problem that call(), apply(), and bind() solve.

call()

call() invokes a function with a specified this value and individual arguments:

function introduce(age, city) {
  console.log(`I am \({this.name}, \){age} years old, from ${city}`);
}

const user = { name: 'Diana' };

introduce.call(user, 28, 'Paris');
// 'I am Diana, 28 years old, from Paris'

First argument is the this context. All subsequent arguments are passed to the function individually.

apply()

apply() does the same thing, but takes arguments as an array:

introduce.apply(user, [28, 'Paris']);
// 'I am Diana, 28 years old, from Paris'

Same result — different argument format. Use apply() when you have arguments as an array.

bind()

bind() doesn't call the function immediately. It returns a new function with this permanently bound:

const boundGreet = introduce.bind(user, 28, 'Paris');

boundGreet();  // 'I am Diana, 28 years old, from Paris'

You can also bind just the this value and pass arguments later:

const boundUser = introduce.bind(user);
boundUser(30, 'London');  // 'I am Diana, 30 years old, from London'

The bound function remembers its context forever. It won't change even if you call it from somewhere else.

Quick Comparison

MethodCalls immediatelyArguments formatReturns
call()YesIndividualFunction result
apply()YesArrayFunction result
bind()No (returns new function)Individual or laterNew function

Practice Assignment

Try these exercises to get comfortable with the concepts:

  1. Create an object with a method that uses this
const calculator = {
  value: 10,
  add: function(n) {
    return this.value + n;
  }
};
  1. Borrow the method using call()
const newObj = { value: 5 };
console.log(calculator.add.call(newObj, 3));  // 8
  1. Use apply() with array arguments
function showTotal(a, b) {
  return this.value + a + b;
}

const context = { value: 100 };
console.log(showTotal.apply(context, [20, 30]));  // 150
  1. Use bind() and store the function
const context = { value: 50 };
const stored = showTotal.bind(context, 10, 20);

console.log(stored());  // 80

Wrapping Up

this is resolved at call time in JavaScript. The three methods — call(), apply(), and bind() — give you control over what this refers to when a function runs.

call() and apply() invoke the function immediately, differing only in argument format. bind() creates a permanent binding, returning a new function you can call later. Once you see the pattern, you'll use these tools to borrow methods, set context, and manage behavior in ways that feel like magic.