手写-call

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' }

实现思路

  1. 普通函数fn本质上也是一个对象,我们将mycall方法挂载到Function.prototype上
    此时调用fn,发现它没有mycall方法,之后就会向原型链上去查找
    找到了mycall方法,此时我们打印this,这个this指向的是fn,也就是谁调用它就指向谁
    此时我们需要更改它的指向
    将需要指向的obj传递进来

  2. 此时在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指向的问题

  1. 下一步是考虑接受参数
    将arguments进行slice切割,之后传递到fn中即可。这里可以回顾一下将arguments为数组转换为数组的几个常用方法
    1. 使用扩展运算符 [...arguments]
    2. Array.from()
    3. Array.prototype.slice.apply(arguments)
    4. 使用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')
posted @ 2022-10-22 17:05  含若飞  阅读(22)  评论(0编辑  收藏  举报