1.手写call
call方法在Function原型对象上,我们自己封装时也需将其挂载到Function原型对象上
// 1.call
Function.prototype.myCall = function(ctx, ...args){
ctx.fn = this, // this指向mycall的调用函数,同时为ctx添加了一个方法fn(即this指向mycall的调用函数)
ctx.fn(...args), //通过ctx执行fn,此时fn中this指向ctx
delete ctx.fn //删除ctx上的fn方法
}
function show1(...args){
console.log(...args);
console.log(this.name);
}
show1.myCall({name:'zhangshan'}, 'zhan', 'li', 'wang')
2.手写apply
写apply的方法与call相似,唯一不同就是传参方式不同,call第二个参数是数据列表,而apply是一个数组
// 2.call
Function.prototype.myApply = function(ctx, args = []){
ctx.fn = this,
ctx.fn(...args),
delete ctx.fn
}
function show2(...args){
console.log(...args);
console.log(this.name);
}
show2.myApply({name:'lisi'}, ['z', 'l', 'w'])
3.手写bind
bind与上面写法类似,不同之处在于bind需手动调用,代码如下
// 3.bind
Function.prototype.myBind = function(ctx, ...args1){
return (...args2) => { //此处需返回一个函数
ctx.fn = this,
ctx.fn(...args1.concat(args2)) //合并参数
delete ctx.fn
}
}
function show3(...args){
console.log(...args);
console.log(this.name);
}
show3.myBind({name:'wangwu'},'zh', 'li', 'wang')('lao')
4.总结
手写call、apply、bind的关键代码是要理解ctx.fn = this这步至关重要的操作