ForgeFrontend — Prepare, Practice, Crack
Secure checkout
Lifetime access
Instant PDF download
Free updates forever

Prepare · Practice · Crack

call vs apply vs bind in JavaScript

Short answer

All three set what `this` refers to inside a function. call invokes it immediately with arguments listed one by one. apply invokes it immediately with arguments in an array. bind invokes nothing — it returns a new function with `this` permanently attached, for you to call later.

callapplybind
Runs immediately?YesYesNo — returns a function
ArgumentsListed: (ctx, a, b)Array: (ctx, [a, b])Listed, and optional
ReturnsThe function's return valueThe function's return valueA new bound function
Can `this` be changed later?n/a — one-offn/a — one-offNo, it's permanent
Works on arrow functions?NoNoNo
Typical useMethod borrowingSpreading an existing arrayCallbacks and handlers
Two questions separate them: does it run now, and how do you hand it the arguments?

The one-line difference

Every function in JavaScript carries an invisible extra parameter called `this`, and normally its value is decided by how the function is called rather than where it was written. These three methods take that decision away from the call site and hand it to you. call and apply do it for a single invocation. bind does it once and for good, producing a new function you can pass around.

Same function, three ways to give it a `this`javascript
1function introduce(role, city) {
2  return `${this.name}${role}, ${city}`;
3}
4
5const arun = { name: "Arun" };
6
7introduce.call(arun, "Frontend Engineer", "Chennai");
8// → "Arun — Frontend Engineer, Chennai"
9
10introduce.apply(arun, ["Frontend Engineer", "Chennai"]);
11// → "Arun — Frontend Engineer, Chennai"      (identical result)
12
13const introduceArun = introduce.bind(arun);
14// → nothing has run yet; introduceArun is a new function
15
16introduceArun("Tech Lead", "Bengaluru");
17// → "Arun — Tech Lead, Bengaluru"

Notice that call and apply produced exactly the same string. That is the honest summary of their relationship: they are the same method with two different argument styles. bind is the one that behaves differently, and it is the one you will reach for most often in real code.

Why `this` needs fixing at all

The reason these methods exist is that `this` is bound at call time, not at definition time. A method pulled off its object forgets where it came from — the function object itself holds no reference back to the owner. This is the single most common source of `undefined` errors in JavaScript, and it is the setup an interviewer is building toward when they ask this question.

A method loses its object the moment you detach itjavascript
1const user = {
2  name: "Divya",
3  greet() { return `Hi, ${this.name}`; },
4};
5
6user.greet();
7// → "Hi, Divya"                 (called as a method — `this` is user)
8
9const greet = user.greet;
10greet();
11// → TypeError: Cannot read properties of undefined (reading 'name')
12//   In strict mode / modules `this` is undefined. In sloppy mode it would be
13//   globalThis, and you would get the equally confusing "Hi, undefined".
14
15greet.call(user);
16// → "Hi, Divya"                 (we supplied the missing `this`)

Every framework callback, every event listener, every setTimeout is a detachment like this one. You pass a function somewhere else, and something else calls it. Unless you have fixed `this` first, the value it sees is whatever the caller decided.

call vs apply: only the arguments differ

Choosing between call and apply is purely mechanical. If you already know the arguments, list them with call. If you already have them in an array, hand the array to apply. Since spread syntax arrived in ES6, apply's one advantage has largely evaporated — you can spread an array into call, or into a plain invocation, and most codebases now do.

apply is mostly a pre-2015 habitjavascript
1const nums = [5, 12, 3, 99, 41];
2
3Math.max.apply(null, nums);
4// → 99            the classic reason apply existed
5
6Math.max(...nums);
7// → 99            the modern equivalent, no `this` juggling at all
8
9// Where apply still reads better: forwarding an unknown argument list
10function withLogging(fn) {
11  return function (...args) {
12    console.log("calling", fn.name);
13    return fn.apply(this, args);   // preserves whatever `this` the caller used
14  };
15}

That last pattern is worth remembering because it is the one place apply genuinely earns its keep. A wrapper does not know how many arguments it will receive or what `this` will be, and `fn.apply(this, args)` forwards both faithfully in one line. Decorators, memoisation helpers and logging wrappers are all built on it.

bind returns a function — and the binding is permanent

bind is the odd one out and the one interviewers push on. It does not call anything. It returns a brand-new function object whose `this` is locked to the value you gave it, forever. You cannot re-bind it, and calling it with call or apply will not override the binding. That permanence is the point: once bound, the function is safe to hand to code you do not control.

Binding cannot be undonejavascript
1function whoAmI() { return this.name; }
2
3const bound = whoAmI.bind({ name: "Arun" });
4
5bound();
6// → "Arun"
7
8bound.call({ name: "Someone else" });
9// → "Arun"          the call() context is ignored entirely
10
11const boundAgain = bound.bind({ name: "Third attempt" });
12boundAgain();
13// → "Arun"          re-binding does nothing either
14
15whoAmI.bind({ name: "X" }) === whoAmI.bind({ name: "X" });
16// → false           every bind() creates a NEW function object

That last line has a practical consequence that catches people in React. Because bind returns a new function every time it runs, calling it inside a render or inside a loop creates a fresh function on every pass. Any child component receiving it as a prop sees a changed prop and re-renders, which is exactly the memoisation problem `useCallback` exists to solve.

This is 1 of 80+ questions in the JavaScript Interview Kit

Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.

⚡ Get the JavaScript Interview Kit → ₹299

Partial application: bind's second job

bind takes arguments after the context, and those arguments are pre-filled into the new function. This is partial application, and it is a genuinely useful technique that comes up in machine-coding rounds when you are asked to build a `curry` or `once` helper. The pre-filled arguments always come first; anything you pass at call time is appended after them.

Pre-filling argumentsjavascript
1function formatPrice(currency, symbolPosition, amount) {
2  return symbolPosition === "prefix"
3    ? `${currency}${amount}`
4    : `${amount}${currency}`;
5}
6
7const inRupees = formatPrice.bind(null, "₹", "prefix");
8
9inRupees(1999);
10// → "₹1999"
11
12inRupees(499);
13// → "₹499"          the first two arguments are baked in
14
15// Order is fixed: bound args first, call-time args after.
16const double = ((a, b) => a * b).bind(null, 2);
17double(21);
18// → 42

Passing `null` as the context, as above, is the standard idiom when the function does not use `this` at all and you only want the argument pre-filling. In strict mode `this` genuinely becomes null inside the function; in sloppy mode it is silently replaced with the global object. Since modules are always strict, this rarely matters in modern code — but it is a fair follow-up question.

Arrow functions ignore all three

An arrow function has no `this` of its own. It closes over the `this` of the scope where it was written, and that binding is decided at definition time and cannot be changed by anything. call, apply and bind will happily accept an arrow function and quietly do nothing to its context. This is the single highest-value follow-up on the whole topic, and a large share of candidates get it wrong.

The context argument is simply ignoredjavascript
1const arrow = () => this?.name;
2const normal = function () { return this?.name; };
3
4const ctx = { name: "Arun" };
5
6normal.call(ctx);
7// → "Arun"
8
9arrow.call(ctx);
10// → undefined        `this` came from the enclosing scope, not from call()
11
12// Same reason this object method is a bug:
13const counter = {
14  count: 0,
15  increment: () => { this.count++; },   // `this` is NOT counter
16};
17counter.increment();
18counter.count;
19// → 0

The flip side is that this behaviour is exactly why arrow functions are the default fix for callbacks inside class methods. There is nothing to lose and nothing to rebind, so an arrow function passed to setTimeout or an event listener keeps the surrounding component's `this` automatically.

The problem bind was invented for, and its modern fixjavascript
1class Timer {
2  constructor() { this.seconds = 0; }
3
4  startBroken() {
5    setInterval(function () {
6      this.seconds++;          // `this` is the timer object, not the Timer
7    }, 1000);
8    // → this.seconds stays 0 forever
9  }
10
11  startWithBind() {
12    setInterval(function () { this.seconds++; }.bind(this), 1000);
13    // → works: 1, 2, 3, …
14  }
15
16  startModern() {
17    setInterval(() => { this.seconds++; }, 1000);
18    // → works, and reads better
19  }
20}

Method borrowing, the real-world use case

Before array-like objects had proper conversion helpers, call and apply were how you borrowed a method from one prototype and pointed it at an object that never inherited it. You still see the pattern in older codebases and in library source, and being able to read it is worth more than being able to write it from scratch.

Borrowing methods that were never yoursjavascript
1// The exact type of any value — still the most reliable check there is
2Object.prototype.toString.call([]);        // → "[object Array]"
3Object.prototype.toString.call(null);      // → "[object Null]"
4Object.prototype.toString.call(new Date());// → "[object Date]"
5
6// Turning an array-like into a real array (pre-ES6 style)
7function legacy() {
8  return Array.prototype.slice.call(arguments);
9}
10legacy(1, 2, 3);
11// → [1, 2, 3]
12
13// The modern equivalents
14function modern(...args) { return args; }         // → [1, 2, 3]
15Array.from(document.querySelectorAll("li"));      // → real array of elements

`Object.prototype.toString.call(value)` is the one to actually keep. `typeof` reports "object" for arrays, null and dates alike, and `instanceof` breaks across iframes and realms. Borrowing toString gives you the internal type tag directly, which is why almost every type-checking utility in every library is built on it.

Implementing them yourselfjavascript
1Function.prototype.myCall = function (ctx, ...args) {
2  ctx = ctx ?? globalThis;
3  const key = Symbol("fn");        // Symbol avoids clobbering a real property
4  ctx[key] = this;                 // `this` is the function myCall was called on
5  const result = ctx[key](...args);
6  delete ctx[key];
7  return result;
8};
9
10Function.prototype.myBind = function (ctx, ...bound) {
11  const fn = this;
12  return function (...later) {
13    return fn.myCall(ctx, ...bound, ...later);
14  };
15};
16
17function hi(greeting) { return `${greeting}, ${this.name}`; }
18hi.myCall({ name: "Arun" }, "Hello");
19// → "Hello, Arun"
20hi.myBind({ name: "Divya" })("Hey");
21// → "Hey, Divya"

Which one should you actually use?

In code written today, bind is the only one of the three you are likely to type deliberately, and even then mostly in class components or when adapting an API that will call your function for you. call survives for method borrowing and type checks. apply survives inside wrappers that forward unknown arguments. Everything else has been replaced by spread syntax and arrow functions.

You want to…Use
Call something once with a chosen `this`call
Forward an unknown argument list inside a wrapperapply
Hand a method to a callback without losing `this`bind, or an arrow function
Pre-fill some argumentsbind(null, …)
Spread an array into a normal callfn(...args) — none of the three
Check an exact typeObject.prototype.toString.call(value)
What to reach for in modern code.

What does bind return exactly?

A new exotic function object with the same body, its `this` fixed, and any pre-filled arguments attached. Its `name` property becomes "bound originalName", its `length` is the original length minus the number of pre-filled arguments, and it has no `prototype` property of its own — which is why you cannot use it as a constructor target in the usual way.

What happens if you use `new` on a bound function?

The bound `this` is ignored and the newly created object wins. This is the one documented exception to bind's permanence: `new` binding outranks bind binding in the precedence order. Any pre-filled arguments are still applied, which makes bind a legitimate, if rare, way to partially apply a constructor.

What is the order of precedence for `this`?

From strongest to weakest: `new` binding, then explicit binding via call/apply/bind, then implicit binding from the object the method was called on, then the default — undefined in strict mode, globalThis in sloppy mode. Arrow functions sit outside this list entirely because they have no `this` of their own.

Does bind work on class methods?

Yes, and it was the standard fix before class fields. `this.handleClick = this.handleClick.bind(this)` in the constructor produces one bound function per instance. A class field with an arrow function — `handleClick = () => {}` — achieves the same thing with less ceremony and is what most codebases use now.

Is there a performance cost to bind?

A bound function adds a small layer of indirection and allocates a new function object, so creating thousands inside a hot render loop is measurably worse than reusing one. Bind once outside the loop and the cost disappears. At normal frequencies it is not something to optimise for.

Frequently asked questions

What is the difference between call, apply and bind in JavaScript?
call and apply both invoke the function immediately with a `this` you choose — call takes arguments one by one, apply takes them in an array. bind invokes nothing; it returns a new function with `this` permanently attached, which you call later. The difference is timing and argument style, not capability.
When should I use bind instead of call or apply?
Use bind when something else will call your function later — an event listener, setTimeout, a promise callback, a prop passed to a child component. Use call or apply when you are invoking the function yourself right now and only need to override `this` for that one call.
Can you change the `this` of a bound function?
No. Once bound, call, apply and even a second bind are ignored. The only exception is `new`: constructing a bound function creates a fresh object that takes priority over the bound context, though any pre-filled arguments still apply.
Do call, apply and bind work with arrow functions?
They run without error but have no effect on `this`. An arrow function captures `this` lexically from the scope where it was defined, and nothing can reassign it afterwards. If you need to control `this`, the function must be a regular function.
What is method borrowing in JavaScript?
Using call or apply to run a method from one object against a different object that never inherited it. The classic examples are Array.prototype.slice.call(arguments) to convert an array-like into a real array, and Object.prototype.toString.call(value) to get a value's exact internal type.
Is apply still useful now that we have spread syntax?
Rarely, but not never. fn(...args) replaces the common Math.max.apply(null, nums) case. apply still reads better inside wrapper functions that must forward both an unknown argument list and the caller's `this` in one expression: fn.apply(this, args).
What does bind(null, x) do?
It pre-fills x as the first argument and sets `this` to null, which is the standard idiom when the function does not use `this` and you only want partial application. Calling the result appends any new arguments after the pre-filled ones.
Why does `this` become undefined when I pass a method as a callback?
Because `this` is decided by how a function is called, not where it was defined. Detaching a method from its object loses that link, so the callback runs with `this` as undefined in strict mode. bind, or an arrow function, restores it.
How do you implement bind from scratch?
Return a closure that calls the original function with the saved context and the pre-filled arguments followed by the call-time ones. Inside, use call or apply with the stored context — or attach the function as a temporary Symbol-keyed property on the context, invoke it as a method, then delete the property.
Does bind create a new function every time it is called?
Yes. Two bind calls on the same function with the same context produce two different function objects that are not equal to each other. This matters in React, where a bind inside render creates a new prop identity on every pass and defeats memoised children.
What is the difference between call and bind in React?
In class components, bind is what you use in the constructor so a handler keeps the component's `this` when React invokes it. call has almost no place in component code. In function components neither applies, because there is no instance `this` to preserve.
What is the precedence order of `this` binding rules?
`new` binding first, then explicit binding via call, apply or bind, then implicit binding from the calling object, then the default binding — undefined under strict mode and globalThis otherwise. Arrow functions bypass all four by inheriting `this` lexically.

This is 1 of 80+ questions in the JavaScript Interview Kit

Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.

⚡ Get the JavaScript Interview Kit → ₹299
Written by Arun Karthikeyan · Last updated

Full kit

JavaScript Interview Kit · ₹299

Get it →