call的作用
function myFn () {
console.log(this.name)
console.log(arguments)
}
const obj = {
name: 'zs'
}
myFn.call(obj,'aaa','bbb')
//call中第一个接收的参数为需要改变的this指向,后续参数为调用参数传参,call会自调用
//运行结果
zs
[Arguments] { '0': 'aa', '1': 'bb' }
实现思路
-
普通函数fn本质上也是一个对象,我们将mycall方法挂载到Function.prototype上
此时调用fn,发现它没有mycall方法,之后就会向原型链上去查找
找到了mycall方法,此时我们打印this,这个this指向的是fn,也就是谁调用它就指向谁
此时我们需要更改它的指向
将需要指向的obj传递进来 -
此时在obj下挂载一个函数,fn2
也就是obj.fn2指向当前的fn函数
就可以通过我们之前的this,
obj.fn2=this
此时
也就是相当于
obj={
name:'zs'
fn2:function(){
return fn(){console.log(this.name)}
}
}
我们在调用fn中的this.name,就会向它的上层中去寻找name,也就是达到了改变this指向的问题
- 下一步是考虑接受参数
将arguments进行slice切割,之后传递到fn中即可。这里可以回顾一下将arguments为数组转换为数组的几个常用方法- 使用扩展运算符
[...arguments]
Array.from()
Array.prototype.slice.apply(arguments)
- 使用for循环遍历,最后返回新数组
- 使用扩展运算符
代码实现
Function.prototype.mycall = function (context) {
// 短路运算符,如果有context,则就是context,否则就等于window
let args = [...arguments].slice(1)
context = context || window
context.fn = this
context.fn(...args)
delete context.fn
}
myFn.mycall(obj, 'aaa', 'bbb')
标签:obj,name,call,arguments,context,手写,fn
From: https://www.cnblogs.com/zx529/p/16816692.html