call 的 polyfill

Function.prototype.call = function(obj){
    // 判断甲方是不是一个函数,不是函数抛出错误
    if(typeof this !== 'function'){
        throw new Error('当前调用 call 方法的不是函数!');
    }

    // 保存甲方给的参数
    const args = [...arguments].slice(1);
    // 确定乙方的类型,因为可以传 null 和 undefined
    obj = obj || window;
    // 将甲方的内容保存为乙方的一个属性,为了保证不与乙方的 key 键名重复
    const fn = Symbol('fn');
    obj[fn] = this;

    const result = obj[fn](...args);
    delete obj[fn];
    return result;
}

apply 的 polyfill

Function.prototype.apply = function(obj){
    if(typeof this !== 'function'){
        throw new Error('当前调用 apply 方法的不是函数!');
    }
    // 此处与 call 有区别
    const args = arguments[1];
    obj = obj || window;
    const fn = Symbol('fn');
    obj[fn] = this;

    const result = obj[fn](...args);
    delete thisArgs[fn];
    return result; 
}

bind 的 polyfill

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被 bind 的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。

 // obj 为要绑定的对象
Function.prototype.bind = function(obj, ...args){
    if(typeof this !== 'function'){
        throw new Error('当前调用 bind 的不是函数');
    }
    // 保存甲方的参数
    var bindArgs = args; 
    var self = this;
    var fBound = function(...args){
        return self.apply(this instanceof fBound? this: obj,                 
                          bindArgs.concat(args));
    }
    Object.setPrototypeOf(fBound, self.prototype);
    return fBound; 
}