On this page
Polyfill for call, apply and bind method
Last reviewed 14 Sept 2026
A polyfill is a piece of code that adds a feature to environments (usually older browsers) that don’t support it natively. It acts like a fallback: if the browser doesn’t have a method, we write our own version.
Writing polyfills for call, apply and bind is a very common interview question, because it tests your understanding of this, prototypes and closures. (See call, apply and bind method for how the real methods work.)
The core trick: when a function is called as a method — obj.fn() — this inside it is obj. So to run a function with a chosen this, we temporarily attach the function to that object, call it as a method, then remove it.
Common setup for all examples:
let name = { firstName: "Rishabh", lastName: "Sisodiya"};
let printName = function (hometown, state) { console.log(this.firstName + " " + this.lastName + ", " + hometown + ", " + state); return "done";};Create a user-defined call method
Simple version
// Real methodprintName.call(name, "Chittorgarh", "Rajasthan");
Function.prototype.mycall = function (obj, ...args) { // this = printName (the function mycall was called on) obj.fnRef = this; // attach the function to obj const result = obj.fnRef(...args); // call it as a method → `this` is obj delete obj.fnRef; // clean up return result;};
printName.mycall(name, "Chittorgarh", "Rajasthan");// "Rishabh Sisodiya, Chittorgarh, Rajasthan"Problem with the simple version: if obj already has a property called fnRef, we overwrite it. And if we forget delete, fnRef stays on the object.
Advanced version
Function.prototype.myCall = function (obj, ...args) { if (typeof this !== "function") { throw new TypeError("myCall must be called on a function"); }
// null/undefined → global object; primitives (e.g. 5, "a") → wrapped in an object obj = obj === null || obj === undefined ? globalThis : Object(obj);
const uniqueKey = Symbol(); // unique key, so no existing property is overwritten obj[uniqueKey] = this; // temporarily store the function on obj const result = obj[uniqueKey](...args); // call the function with the arguments delete obj[uniqueKey]; // remove the temporary property return result; // return the function's result};
console.log(printName.myCall(name, "Chittorgarh", "Rajasthan"));// "Rishabh Sisodiya, Chittorgarh, Rajasthan"// "done"console.log(Object.getOwnPropertySymbols(name).length); // 0 — nothing left behindWhy Object(obj) instead of obj || globalThis? obj || globalThis would also replace valid falsy values like 0 or "" with the global object, and you cannot add properties to primitives.
Create a user-defined apply method
apply is the same as call, except the arguments come as an array.
Simple version
// Real methodprintName.apply(name, ["Chittorgarh", "Rajasthan"]);
Function.prototype.myapply = function (obj, args) { if (!Array.isArray(args)) { throw new TypeError("CreateListFromArrayLike called on non-object"); } // this = printName obj.fnRef = this; const result = obj.fnRef(...args); delete obj.fnRef; return result;};
printName.myapply(name, ["Chittorgarh", "Rajasthan"]);// "Rishabh Sisodiya, Chittorgarh, Rajasthan"
// printName.myapply(name, "Chittorgarh", "Rajasthan");// TypeError: CreateListFromArrayLike called on non-object — arguments must be in an arrayAdvanced version
Function.prototype.myApply = function (obj, args) { if (typeof this !== "function") { throw new TypeError("myApply must be called on a function"); } if (args !== null && args !== undefined && typeof args !== "object") { throw new TypeError("CreateListFromArrayLike called on non-object"); }
obj = obj === null || obj === undefined ? globalThis : Object(obj);
const uniqueKey = Symbol(); obj[uniqueKey] = this; const result = obj[uniqueKey](...Array.from(args || [])); // supports arrays and array-likes delete obj[uniqueKey]; return result;};
printName.myApply(name, ["Udaipur", "Rajasthan"]);// "Rishabh Sisodiya, Udaipur, Rajasthan"
console.log(Math.max.myApply(null, [3, 9, 2])); // 9Once myCall exists, myApply can also be written in one line:
Function.prototype.myApply2 = function (obj, args = []) { return this.myCall(obj, ...args);};Create a user-defined bind method
bind does not call the function. It returns a new function that remembers obj and any arguments passed so far (using a closure), and calls the original function later.
// Real methodlet printMyName = printName.bind(name, "Chittorgarh");printMyName("Rajasthan");// "Rishabh Sisodiya, Chittorgarh, Rajasthan"Simple version
Function.prototype.mybind = function (obj, ...args) { if (typeof this !== "function") { throw new TypeError("myBind must be called on a function"); } const func = this; // save the original function (closure)
return function (...innerArgs) { // combine arguments from mybind with arguments from the returned function return func.apply(obj, [...args, ...innerArgs]); };};
let printMyName2 = printName.mybind(name, "Chittorgarh");printMyName2("Rajasthan");// "Rishabh Sisodiya, Chittorgarh, Rajasthan"Why do we need const func = this? Inside the returned function, this would be different (it depends on how the returned function is called). Saving it in func lets the closure remember the original function.
Without using apply/call (advanced)
Function.prototype.myBind = function (obj, ...args) { if (typeof this !== "function") { throw new TypeError("myBind must be called on a function"); } const func = this; const context = obj === null || obj === undefined ? globalThis : Object(obj);
return function (...innerArgs) { const uniqueKey = Symbol(); context[uniqueKey] = func; // attach at call time const result = context[uniqueKey](...args, ...innerArgs); delete context[uniqueKey]; // clean up after each call return result; };};
let printMyName3 = printName.myBind(name, "Chittorgarh");printMyName3("Rajasthan");// "Rishabh Sisodiya, Chittorgarh, Rajasthan"(The key is attached inside the returned function, at call time, so the object is not left with an extra property between calls.)
Supporting new (bonus)
The real bind lets you use new on a bound function; in that case the bound this is ignored. A polyfill that supports this:
Function.prototype.myBindWithNew = function (obj, ...args) { const func = this;
function bound(...innerArgs) { const isNew = this instanceof bound; // called with new? return func.apply(isNew ? this : obj, [...args, ...innerArgs]); }
bound.prototype = Object.create(func.prototype); // keep the prototype chain return bound;};
function Person(first, last) { this.full = first + " " + last;}
const BoundPerson = Person.myBindWithNew({ ignored: true }, "Rishabh");const p = new BoundPerson("Sisodiya");console.log(p.full); // "Rishabh Sisodiya"console.log(p instanceof Person); // trueChecking if a native method exists (real polyfill style)
Real polyfills only add the method if the browser doesn’t already have it:
if (!Function.prototype.bind) { Function.prototype.bind = function (obj, ...args) { const func = this; return function (...innerArgs) { return func.apply(obj, [...args, ...innerArgs]); }; };}Interview practice: Interview version, built step by step — including
newon a bound function: Machine Coding — call, apply and bind.