Tworzymy polyfill dla funkcji apply na podstawie już opracowanego dla funkcji call. Kończymy polifille call/apply/bind.

Zobaczmy raz jeszcze jak działa call:

function greet(showAge=false){
    let msg = `Hi my name is ${this.name}`;
    if(showAge)
        msg += ` and Im ${this.age} years old`;
    return msg;
}

const obj = {
    name: 'John',
    age: 30,
    myFn(){
        console.log("My fn");
    }
};

Function.prototype.myCall = function(obj, ...args){
    let fn=this;
    if(typeof fn !== "function"){
        throw new Error('Invalid function provided for binding.');
      }
    let myFn = Symbol('myFn');
    obj[myFn] = this;
    let result = obj[myFn](...args);
    return result;
    
}

obj.myFn();
//My fn
console.log(greet.myCall(obj, true));
//Hi my name is John and Im 30 years old
obj.myFn();
//My fn

Apply nie różni się niczym w działaniu, natomiast inaczej argumenty zbiera. Niewielka poprawka:

//(...)

Function.prototype.myApply = function(obj, args){
    let fn=this;
    if(typeof fn !== "function"){
        throw new Error('Invalid function provided for binding.');
      }
    let myFn = Symbol('myFn');
    obj[myFn] = this;
    let result = obj[myFn](...args);
    return result;
    
}

obj.myFn();
//My fn
console.log(greet.myCall(obj, true));
//Hi my name is John and Im 30 years old
console.log(greet.myApply(obj, [true]));
//Hi my name is John and Im 30 years old
obj.myFn();
//My fn

Ok, call, apply oraz bind mamy za sobą.