cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

call, apply & bind

Learn how call, apply, and bind set this explicitly, pass arguments, borrow methods, create partial applications, and build a simplified bind helper.

By the end, you can
  • 01
    Choose call, apply, or bindDecide whether to run now with listed arguments, run now with an array, or create a reusable bound function.
  • 02
    Borrow safe methodsUse array and object methods on compatible values without trusting the target object.
  • 03
    Write a small bind helperImplement the normal-call behavior of bind with apply, rest parameters, and spread.

Explicit this in one sentence

The previous lesson, The this keyword, introduced the four binding rules: default, implicit, explicit, and new. This lesson zooms in on explicit binding: choosing this yourself with call, apply, or bind.

Here is the core idea: call and apply run a function now with a chosen this; bind creates a new function that remembers a chosen this for later. They do not change the original function. They only decide how it is invoked.

Real-life analogyA friend's phone for one call

Imagine borrowing Ada's phone to make one call. call and apply use Ada for this one call; apply takes the extra words from an array. bind is saving Ada on speed dial for later.

In real life: Use Ada's phone for one call
In JavaScript: introduce.call(ada, "Hello", "!")
In real life: Use Ada's phone with contacts in a list
In JavaScript: introduce.apply(ada, ["Hello", "!"])
In real life: Save Ada on speed dial
In JavaScript: introduce.bind(ada) returns a new function

Where the analogy stops: A real phone can call anyone. A bound function keeps its chosen this, even after .call(other).

Definition

Function.prototype.call, apply, and bind are methods on functions. They let a normal function run with an explicit this value and, in the case of bind, optionally remember some arguments too.

You will also borrow methods from built-in objects, then write a small myBind helper. Later lessons named Currying & partial application and Polyfill call, apply & bind go deeper; here we build the accurate everyday model.

call vs apply

INTERACTIVE

call and apply are twins. Both run the function immediately. Their first argument is the value to use as this. The difference is how the remaining arguments are delivered.

call, apply, and bind at a glance
MethodRun/returnArgument style
callRuns now; returns the function's resultList arguments one by one
applyRuns now; returns the function's resultPass one array-like argument bag
bindRuns later; returns a new functionList preset arguments one by one

Try the same introduce function with different target objects. The code line shown is the line you would type in a console.

call/apply/bind console playground
Equivalent codePop out in the code editor (opens in a new tab)JavaScript
function introduce(greeting, punctuation) {  return `${greeting}, I'm ${this.name}${punctuation}`;} const ada = { name: "Ada" };const grace = { name: "Grace" };const linus = { name: "Linus" }; introduce.call(ada, "Hello", "!");
Real resultcall
Target thisAda
Return valueHello, I'm Ada!
Equivalent callintroduce.call(ada, "Hello", "!")
Try it yourself

call uses one chosen phone for this call. The normal arguments are listed one by one.

Change the invocation style and target object. The result is produced by real JavaScript functions in this lesson.

The important part is not where the function was written. It is how it is called. introduce.call(ada, "Hello", "!") says: “Run introduce now, and inside it make this be ada.” apply says the same thing, but it accepts ["Hello", "!"] as the argument bag. Remember a for array.

Run call and apply
Step 0 of 5Ready
Your turn: follow the blue line

Predict each return value. call and apply both run immediately; only the argument packaging changes.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
  return `${greeting}, I'm ${this.name}${punctuation}`;} const ada = { name: "Ada" };const grace = { name: "Grace" }; introduce.call(ada, "Hello", "!");introduce.apply(grace, ["Hi", "."]);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

bind & partial application

STEP THROUGH

bind does not run the function. It returns a new function. That new function remembers the this value you gave it. It can also remember one or more leading arguments. Saving some arguments now and supplying the rest later is called partial application.

Real-life analogyA saved contact

bind is like saving Ada as a contact before you need to call. When you use it later, Ada is already chosen. A pre-filled form can also save the first value, leaving fewer values for later.

In real life: Save Ada as the contact
In JavaScript: introduce.bind(ada) locks this to Ada
In real life: Pre-fill the first blank on a form
In JavaScript: multiply.bind(null, 2) saves the first argument
In real life: Tap the saved contact later
In JavaScript: The returned function can be used as a callback later

Where the analogy stops: You can edit a real contact. A bound function's this cannot be changed by call or apply.

What bind really creates
Step 0 of 11Ready
Your turn: follow the blue line

Step through the odd facts that make bind different from call and apply.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
  return `${greeting}, I'm ${this.name}${punctuation}`;}function multiply(a, b) {  return a * b;} const ada = { name: "Ada" };const grace = { name: "Grace" };const adaIntro = introduce.bind(ada, "Hello");const double = multiply.bind(null, 2); adaIntro.call(grace, "!");double === multiply;double(5);double.name;double.length; function Person(name) {  this.name = name;}const BoundPerson = Person.bind({ name: "Ignored" });const student = new BoundPerson("Maya");student.name;
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Choose a prediction focus before stepping

Watch line 13: the bound this wins.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Notice the professional edge cases: a bound function is not identical to the original; name often starts with "bound "; length is reduced by the number of preset arguments; and if you call a bound function with new, the new object becomes this instead of the bound object.

Method borrowing

STEP THROUGH

Method borrowing means using a method from one value on another value that has a compatible shape. The Iterating arrays lesson introduced array-like values; now you can see why borrowing array methods works.

Real-life analogyBorrowing a friend's phone

A friend's phone can make one call for you without becoming your phone. In JavaScript, arguments has numbered items and a length, so an array method that needs only those features can use it for one call.

In real life: Your phone has a number but cannot make calls
In JavaScript: arguments is indexed but lacks array methods
In real life: Use your friend's phone once
In JavaScript: Array.prototype.slice.call(arguments)
In real life: Give the phone back
In JavaScript: The method runs immediately and nothing is installed on arguments

Where the analogy stops: A borrowed phone only works with a usable number. Borrowed methods need the properties they expect.

Borrow methods safely
Step 0 of 8Ready
Your turn: follow the blue line

Method borrowing is using a method from one kind of value on another compatible value.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
  const args = Array.prototype.slice.call(arguments);  return args.join(" | ");} const letters = Array.prototype.join.call("abc", "-");const nums = [4, 9, 2];const biggestOld = Math.max.apply(null, nums);const biggestNow = Math.max(...nums);const hasName = Object.prototype.hasOwnProperty.call({ name: "Ada" }, "name");const hasNameModern = Object.hasOwn({ name: "Ada" }, "name");collect("red", "green", "blue");
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Modern JavaScript often has clearer alternatives: Math.max(...nums) instead of Math.max.apply(null, nums), and Object.hasOwn(obj, key) instead of borrowing hasOwnProperty. Still, reading older code and writing defensive utilities requires understanding the borrowed-method pattern.

Writing a bind polyfill

STEP THROUGH

A real polyfill would carefully match the language specification and patch Function.prototype only when needed. For a lesson, patching global prototypes in site code would be noisy, so we will write a helper function instead: myBind(fn, thisArg, ...preset).

Simplified helperPop out in the code editor (opens in a new tab)JavaScript
function myBind(fn, thisArg, ...preset) {
  return function boundFunction(...args) {
    return fn.apply(thisArg, [...preset, ...args]);
  };
}

function introduce(greeting, punctuation) {
  return `${greeting}, I'm ${this.name}${punctuation}`;
}

const ada = { name: "Ada" };
const sayHello = myBind(introduce, ada, "Hello");
sayHello("!");
Build a simplified myBind
Step 0 of 5Ready
Your turn: follow the blue line

This is a simplified helper, not a complete spec replacement for native bind.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
  return function boundFunction(...args) {    return fn.apply(thisArg, [...preset, ...args]);  };} function introduce(greeting, punctuation) {  return `${greeting}, I'm ${this.name}${punctuation}`;} const ada = { name: "Ada" };const sayHello = myBind(introduce, ada, "Hello");sayHello("!");
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
What this helper intentionally misses

This simplified version matches native bind for normal calls with a fixed this and preset arguments. It does not implement constructor behavior with new, native name and length metadata, or every specification detail. The later Polyfill call, apply & bind lesson builds the fuller version.

Where you’ll use this

These methods appear most often in four places. First, event handlers and timers may call a method without its object, so bind can preserve the intended receiver. The later Losing this lesson focuses on that bug; here is the preview:

Bind as a callback fixPop out in the code editor (opens in a new tab)JavaScript
const counter = {
  count: 0,
  increment() {
    this.count += 1;
    console.log(this.count);
  }
};

setTimeout(counter.increment.bind(counter), 1000);

Second, utilities can partially apply a function: const logError = console.error.bind(console, "Error:"). Third, libraries borrow methods defensively, especially hasOwnProperty. Fourth, older code uses apply to turn arrays into argument lists; newer code usually uses spread.

call, apply, or bind?
  • Run introduce now with ada, "Hi", and "!" listed separately
  • Run Math.max now with numbers already stored in nums
  • Hand a method to a timer without losing its object
  • Create double from multiply by saving the first argument as 2
  • Turn arguments into a real array using Array.prototype.slice
  • Use a single bag of arguments named args
Try it yourself
0 of 6 correct

Sort each task by the best function method.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Common misconceptions

  • “call changes the function forever.” No. It chooses this for one immediate run.
  • “apply is older bind.” No. apply runs now with an array of arguments; bind returns a function for later.
  • “bind only fixes this.” It can also preset arguments, which is partial application.
  • “A bound function’s this can be replaced with call.” No. A later call can pass more arguments, but the bound this stays.
  • “Borrowed methods work on anything.” They only work when the target has the shape the method expects.
  • “Our myBind is a complete polyfill.” It teaches the core forwarding idea, but skips new, name, and length details.
The safest mental model

Read the method name as a scheduling decision: call and apply mean “run now”; bind means “prepare a new function for later.”

Practice exercises

5 EXERCISES
Exercise 1 · Warm-upPredict a call result
What does this program print?
Starter codePop out in the code editor (opens in a new tab)JavaScript
function introduce(greeting) {
  return greeting + ", " + this.name;
}
const ada = { name: "Ada" };
console.log(introduce.call(ada, "Hi"));

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeBorrow join for a string
    Use method borrowing to produce a-b-c from the string abc.
    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const result = Array.prototype.join.call("abc", "-");
    console.log(result);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFix a timer callback
      A delayed callback loses its object. Bind the method so it increments counter.count.
      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const counter = {
        count: 0,
        increment() {
          this.count += 1;
          console.log(this.count);
        }
      };
      const later = counter.increment.bind(counter);
      later();

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeCreate a partially applied function
        Create triple by binding the first argument of multiply.
        Starter codePop out in the code editor (opens in a new tab)JavaScript
        function multiply(a, b) {
          return a * b;
        }
        const triple = multiply.bind(null, 3);
        console.log(triple(4));

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeImplement myBind
          Write the simplified helper from the lesson and prove it matches native bind for normal calls.
          Starter codePop out in the code editor (opens in a new tab)JavaScript
          function myBind(fn, thisArg, ...preset) {
            return function boundFunction(...args) {
              return fn.apply(thisArg, [...preset, ...args]);
            };
          }
          function introduce(greeting, punctuation) {
            return greeting + ", I'm " + this.name + punctuation;
          }
          const ada = { name: "Ada" };
          const sayHello = myBind(introduce, ada, "Hello");
          console.log(sayHello("!"));

          Answer, then press Check. Spacing and letter case don’t matter.

            Check your understanding

            7 QUESTIONS
            call, apply & bind quiz · 7 questionsScore: first tries count
            1. Question 1 of 7Which method runs a function immediately while setting this and listing arguments one by one?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does this call snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function show(punctuation) {
                console.log(this.name + punctuation);
              }
              show.call({ name: "Ada" }, "!");

              Choose an answer to see the explanation.

            3. Question 3 of 7What does this apply snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function add(a, b) {
                console.log(a + b);
              }
              add.apply(null, [2, 5]);

              Choose an answer to see the explanation.

            4. Question 4 of 7What does this bound multiply snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function multiply(a, b) {
                console.log(a * b);
              }
              const double = multiply.bind(null, 2);
              double(6);

              Choose an answer to see the explanation.

            5. Question 5 of 7What does this bound this snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function show() {
                console.log(this.name);
              }
              const bound = show.bind({ name: "Ada" });
              bound.call({ name: "Grace" });

              Choose an answer to see the explanation.

            6. Question 6 of 7Which line is the safest classic property check for a key that came from a user?

              Choose an answer to see the explanation.

            7. Question 7 of 7What does the simplified myBind in this lesson intentionally miss?

              Choose an answer to see the explanation.

            Key takeaways

            • call(thisArg, ...args) runs now and lists arguments one by one.
            • apply(thisArg, argsArray) runs now and takes arguments from one array-like value.
            • bind(thisArg, ...preset) returns a new function that remembers this and optional leading arguments.
            • Borrowing methods works when the borrowed method’s expectations match the target’s shape.
            • A simplified bind helper is fn.apply(thisArg, [...preset, ...args]) inside a returned function, but native bind does more.

            Final definition: These function methods choose this: call and apply run immediately; bind prepares a reusable function.

            Up next: Arrow functions & lexical this.

            CompleteFrontend Clear concepts. Working examples.