call,apply,bind,最简单的实现

158 阅读2分钟

前言

提到this指向改变方式,绕不过去的三座大山,call,apply,bind,没有广告,单纯记录下自己的手写过程,仅供参考.

call,apply,bind的区别

这篇文章总结的很全:call,apply,bind的区别

this对象+要调用的目标方法

  1. this对象
const zoeInfo={
  name:"Zoe",
  age:"27"
}
  1. 要调用的目标方法
const targetFunc=function(...role){
  console.log([this.name,this.age,...role])
}

call的实现

  1. 根据mdn 对call的描述我们确定需求

image.png

  • 支持多个参数,除了第一个参数this ,其余为目标函数的入参
  • this改变指向后需立即执行
  • 另外补充一点,this不传时候 默认指向window

2.思路

  • 将目标函数设为目标对象(this)的属性
  • 执行该函数
  • 删除该函数

3.代码实现

Function.prototype.myCall=function(context){
//不传this时 避免报错,默认指向window对象
  var context=context||window
  //将函数设为对象的属性 ,有疑惑的小伙伴 可以在这里console下这里的this
  context.fn=this
   let arr=[]
   //这里i从1开始,因为第一参数是this
   for(let i=1;i<arguments.length;i++){
     arr.push('arguments['+i+']')
   }
   //eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。
  const result=eval( 'context.fn('+arr+')')
  //删除该函数
   delete  context.fn
  //return执行该函数
 return result
}

4.调用

targetFunc.myCall(zoeInfo,"前端菜🐔")

5.效果

image.png

bind的实现

  1. 根据mdn 对apply的描述我们确定需求

image.png

  • 和call的区别是 第二参数得是一个数组
  • 效果相同
  1. 思路
  • 同 call 一样

3.代码实现

Function.prototype.myApply=function(context,arr=[]){
  //不传this时 避免报错,默认指向window对象
  var context=context||window
  context.fn=this
  //不传第二参数,直接调用  然后return
  if(!arr.length){
    context.fn()
    delete context.fn
     return
  }
  let args=[]
  //和call有些些区别,arr 已经设置了默认值[],就是指向apply的第二参数
  //i无需从1开始遍历
  for(let i=0;i<arr.length;i++){
    args.push('arr['+i+']')
  }
  const result=eval('context.fn('+args+')')
  delete context.fn
  return result
}

4.调用

targetFunc.myApply(zoeInfo,["前端菜🐔","努力学习中"])

5.效果

image.png

apply的实现

  1. 根据mdn 对call的描述我们确定需求

image.png

  • 参数:第一参数得是一个函数,第二参数是数组
  • 返回值是一个新函数
  • 不会自动执行,需要手动调用
  • 这里先偷个懒,没有考虑绑定函数也可以使用 new 运算符构造(回头有时间 再来填坑)

2.代码实现

  • 借助已经实现的apply方法
 Function.prototype.myBind=function(contex,arr=[]){
   if(typeof(this)!=='function'){
     throw new Error('first param not a function')
   }
  var self=this
   return function(){
   self.apply(contex,arr);
  };
 
}

3.调用

const bindFunc=targetFunc.myBind(zoeInfo,["前端菜🐔","努力学习中","bind的代码实现"])
bindFunc()

4.效果

image.png

小结

没有最好的实现,只有更好的实现,欢迎评论区给出更好的实践和评论,请多指教 编辑器:jsbin

最后如果觉得本文有帮助 记得点赞三连哦 十分感谢