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)
或者使用[].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])
}
}