From call() to Composition: A JavaScript Context Journey

OleksiiOleksii
3 min read

Mastering call, apply, bind, and this in JavaScript (even if you haven’t used them in years)

After two years of working almost exclusively with the Vue Composition API, I realized something odd: I hadn’t written a single line using call, apply, or bind. And more surprisingly — I almost never had to deal with this.

Why? Because the Composition API largely eliminates the need for dealing with this altogether.

In this article, I’ll go over what this, call, apply, and bind are in JavaScript, and also explain why the modern Vue Composition API lets you avoid them entirely — without losing functionality.

this: The Context Chameleon

this refers to the object that is executing the current function. Depending on how a function is called, this can be:

  • A global object (in non-strict mode)

  • undefined (in strict mode)

  • A DOM element (in event listeners)

  • The object that owns the method

That’s why this is tricky — it depends on the call site.

call(): Invoke and Set this

function greet() {
  console.log(`Hello, my name is ${this.name}`);
}

const user = { name: 'Alex' };
greet.call(user); // Hello, my name is Alex

You call the function and explicitly pass the this value.

apply(): Like call, But With Arrays

function sum(a, b) {
  return a + b;
}

console.log(sum.apply(null, [2, 3])); // 5

Perfect for spreading arguments into functions.

bind(): Returns a New Function With Bound this

const alex = {
  name: 'Alex',
  greet() {
    console.log(`Hi, I'm ${this.name}`);
  },
};

const greet = alex.greet.bind(alex);
setTimeout(greet, 1000); // Hi, I'm Alex

Use bind() when you want to preserve this in callbacks or event handlers.

So Why Don’t We Use this in Vue Composition API?

One of the biggest advantages of the Vue Composition API is that it lets you avoid this altogether.

Why?

  • In the Options API, you’d often write this.count, this.message, and bind methods to this.

  • In Composition API, everything is declared inside setup() and returned — so you just use variables directly:

setup() {
  const count = ref(0);
  const increment = () => count.value++;
  return { count, increment };
}

No this, no ambiguity. Just clean, functional code.

This makes the Composition API easier to read, test, and use with TypeScript. It’s part of why it feels so modern.

But if you're diving into legacy codebases or vanilla JS — knowing how this works is still essential.

Final Thoughts

Even if you don’t use these methods daily — especially when working in frameworks like Vue — knowing how they work helps with debugging, reading legacy code, and writing more flexible functions.

This was a great refresher for me — and I hope it helps you too!

Let me know in the comments: When was the last time you used call, apply, or bind in a real project?

0
Subscribe to my newsletter

Read articles from Oleksii directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Oleksii
Oleksii

Frontend developer focused on Vue 3, Nuxt, TypeScript & Tailwind. Writing clean, scalable code and sharing what I learn along the way.