js手写系列之实现call、apply、bind

106 阅读1分钟

call, apply, bind都是js中改变this指向的方法。但它们之中又有些区别,个人感觉,要想熟记他们之间的区别,最好是使用原生js来实现一遍。 那么这几个方法干了几件事儿呢?先上代码。

var myObj = {
    name: '无名小兵'
}
function printName(param){
    console.log(param)
    console.log(this.name)
}
printName.call(myObj, '小二');

我们可以理解为,就是给call的首个参数(比如myObj对象),上面挂了一个属性,这个属性值就是printName对应的这个函数体。给printName传入的函数参数就是call的其他参数(除第一个参数以外的参数)。 我们要实现自己的call方法,一定是要挂在Funtion对应的原型上的。 假代码逻辑就是

  • 先将原函数挂到目标对象上。
  • 收集调用函数的参数。 (在第二步的时候看很多文章都是这样来收集arguments)

111.jpeg 或者使用[].slice.call(arguments,1),其实直接在定义函数的时候直接function(context,...args)即可。

  • 调用函数,并传入参数。
  • 删除目标对象挂在的fn属性。 现在开始尝试书写。
Function.prototype.myCall = function(context,...args){
    context.fn = this;//
    //给传入的对象上挂一个fn名称的属性,属性值就是this,因为调用的时候是这样的,printName.call(myObj, '小二'),fn的值就是this即printName。
    const result = context.fn(...args);
    delete context.fn;
    return result
}

手写myApply 同上,换个名字就行了

Function.prototype.myApply = function(context, ...args){
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
}

手写实现myBind

Funtion.prototype.myBind = function(context, ...args){
    const self = this;
    return function F(){
        return f.apply(context, [...args, ...arguments])
    }
    
}