call、apply、bind手写实现

call的实现

call的第一个参数是指向值,如果为null或者undefined则是,this指向window

第二个参数是以一个一个传入

Function.prototype.fancall=function(context,...arg){
    //如果是null和undefined的时候就指向全局
    if(context==null||context==undefined)
    context=window

    let tem=Symbol()  //做一个唯一值 防止于原上下文对象属性冲突
    context[tem]=this //函数隐试绑定到context上 
    let res = context[tem](...arg) //传参执行  就是function() 执行
    delete context[tem]  //删除临时属性
    return res
}

apply实现

唯一不同就是传参方式不同

Function.prototype.fanapply=function(context){
    //如果是null和undefined的时候就指向全局
    if(context==null||context==undefined)
    context=window

    let arr=arguments[1] //获取数组参数 就是第二个
    console.log(arr);
    let tem=Symbol()  //做一个唯一值 防止于原上下文对象属性冲突
    context[tem]=this //函数隐试绑定到context上 
    let res

    if(arr){
         res = context[tem](arr) //传参执行  就是function() 执行
    }
    else{
         res = context[tem]() //传参执行  就是function() 执行
    }
    
    delete context[tem]  //删除临时属性
    return res
}

bind实现

虽然bind和其余两个一样都是改变this的指向,但bind是返回一个新的函数,而不是直接执行

  • 箭头函数的 this 永远指向它所在的作用域
  • 函数作为构造函数用 new 关键字调用时,不应该改变其 this 指向,因为 new绑定 的优先级高于 显示绑定硬绑定
Function.prototype.fanbind=function(context){
    if(typeof this!=='function')
    throw new TypeError(`Error`)

    let _this =this
    let arr=Array.prototype.slice.call(arguments,1) //获取参数

    var profunction=function(){}//用于继承原型链

    var F=function (){

        if(this instanceof F){
            //如果是被当做构造函数调用,第一个参数作废 当为构造函数的时候this指向实例
            return _this.apply(this,arr.concat([...arguments]))
        }
            //否则就是原先的调用对象
            return _this.apply(context,arr.concat([...arguments]))
    }

    profunction.prototype=this.prototype //继承原本函数的原型
    F.prototype=new profunction()

    return F

}

实例

var value = 2;

var foo = {
    value: 1
};

function bar(name, age) {
    this.habit = 'shopping';
    console.log(this.value);
    console.log(name);
    console.log(age);
}

bar.prototype.friend = 'kevin';

var bindFoo = bar.fanbind(foo, 'daisy');

var obj = new bindFoo('18');
// undefined
// daisy
// 18
console.log(obj.habit);
console.log(obj.friend);
// shopping
// kevin