Custom Polyfills for JavaScript Call, Apply, and Bind

Classified in Technology

Written on in English with a size of 5.7 KB

Custom Call, Apply, and Bind Implementations

In JavaScript, Function.prototype.call, apply, and bind allow developers to explicitly set execution context (the this value). Below are custom implementations (polyfills) for these methods.

1. Custom Call Polyfill (myCall)

The myCall method invokes a function with a specified context and arguments passed individually:

if (!Function.prototype.myCall) {
    Function.prototype.myCall = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return thisArg.fn(...args);
    };
}

2. Custom Apply Polyfill (myApply)

The myApply method invokes a function with a specified context and arguments provided as an array or array-like object:

if (!Function.prototype.myApply) {
    Function.prototype.myApply = function(thisArg, args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return context.fn(...args);
    };
}

3. Custom Bind Polyfill (myBind)

The myBind method creates a new bound function that, when executed, calls the original function with the supplied context and combined arguments:

if (!Function.prototype.myBind) {
    Function.prototype.myBind = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return (...rest) => thisArg.fn.myApply(thisArg, [...args, ...rest]);
    };
}

Repetition Set 2

Implementation of myCall

if (!Function.prototype.myCall) {
    Function.prototype.myCall = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return thisArg.fn(...args);
    };
}

Implementation of myApply

if (!Function.prototype.myApply) {
    Function.prototype.myApply = function(thisArg, args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return context.fn(...args);
    };
}

Implementation of myBind

if (!Function.prototype.myBind) {
    Function.prototype.myBind = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return (...rest) => thisArg.fn.myApply(thisArg, [...args, ...rest]);
    };
}

Repetition Set 3

Implementation of myCall

if (!Function.prototype.myCall) {
    Function.prototype.myCall = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return thisArg.fn(...args);
    };
}

Implementation of myApply

if (!Function.prototype.myApply) {
    Function.prototype.myApply = function(thisArg, args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return context.fn(...args);
    };
}

Implementation of myBind

if (!Function.prototype.myBind) {
    Function.prototype.myBind = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return (...rest) => thisArg.fn.myApply(thisArg, [...args, ...rest]);
    };
}

Repetition Set 4

Implementation of myCall

if (!Function.prototype.myCall) {
    Function.prototype.myCall = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return thisArg.fn(...args);
    };
}

Implementation of myApply

if (!Function.prototype.myApply) {
    Function.prototype.myApply = function(thisArg, args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return context.fn(...args);
    };
}

Implementation of myBind

if (!Function.prototype.myBind) {
    Function.prototype.myBind = function(thisArg, ...args) {
        if (typeof this !== "function") {
            throw new TypeError(`${thisArg} can only be used on functions`);
        }

        const context = thisArg || window;
        context.fn = this;

        return (...rest) => thisArg.fn.myApply(thisArg, [...args, ...rest]);
    };
}

Related entries: