1、call方法,fn1.call(fn2,参1,参2....)
function add(num1, num2) {
console.log(this,"<----add");
console.log(num1 + num2);
}
function sub(num1, num2) {
console.log(this,"<----sub");
console.log(num1 - num2);
}
Function.prototype.myCall = function(context) {
const args = [...arguments].slice(1) //截取出入参
context = context || window //如果context未传,则默认为window
context.fn = this //这里的this指调用者,add调用mycall,所以this指向add,
//往context上增加一个中间属性fn,指向this,this就是add函数
const results = context.fn(...args) //将剩余参数传入,此时调用者为context,
//即sub调用了fn
return results
}
add.myCall(sub,5,2)
从打印结果可以看出,add中的this变成了函数sub,已经指向了传入函数。
2、apply方法,fn1.apply(fn2,【参1,参2....】)
Function.prototype.myApply = function (context) {
let result = null;
context = context || window;
context.fn = this;
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
return result;
};
function Add(num1, num2) {
console.log(this,"<------add");
console.log(num1 + num2);
}
function Sub(num1, num2) {
console.log(this,"<------sub");
console.log(num1 - num2);
}
Add.myApply(Sub, [6, 3]);
同call一般,apply传递数组的处理方式相近,此时打印结果,依然完成实现。
3、bind方法,fn = fn1.bind(fn2,参1,参2.....)
Function.prototype.myBind = function (context) {
// 获取参数
var args = [...arguments].slice(1), // [1,5]
fn = this; //fn指向调用者this(add)
// console.log(this);//Add
return function Fn() {
//对实际调用的传参进行处理
const bindArgs = Array.prototype.slice.call(arguments)
// console.log(this); //Window
return fn.apply(context, args.contact(bindArgs));//将后传的参数拼接进去
};
};
function Add(num1, num2) {
console.log(this);
console.log(num1 + num2);
}
function Sub(num1, num2) {
console.log(num1 - num2);
}
var newFun = Add.myBind(Sub, 1, 5);
newFun(3); //返回的函数在实际调用时,也可以传参
bind函数返回的是一个新函数,在实现时候借用了apply方法。(注意返回的函数在实际调用时,也可以传参)