手写call,apply,bind

实现call

Function.prototype.myCall = function(context){
    if(typeof this != 'function')
      throw new Error('type Error');
    context = context || window//context上下文,指要指向的对象
    const args = [...arguments].slice(1);//接收到的参数,因为第一个参数为要改变的this,不加入参数列表,用数组包裹是因为arguments不能作为数组使用slice方法
    context.fn = this//把fn函数为this,因为this就是一个函数
    let ans = context.fn(...args);//核心代码此时fn为this函数,调用改函数,因为调用者为context,可以改变改函数的this了
    delete context.fn//只删除对象的fn函数
    return ans;
  }
  function Fn(name) {
    this.name = name;
    console.log(this.name);
  }
  let obj = {
    ha: 'uuu'
  }
  Fn.myCall(obj,'han')
  console.log(obj.name);//han

具体步骤可以分为:

  1. 先判断context,即改变this的对象判断指向是否为空,即window。
  2. 处理拿过来的参数列表,借用赋值运算符用数组装起来
  3. 新增context一个函数,该函数的目的是作为中间值存调用者this函数,也就是请求更改this的函数
  4. 根据call特性,会自动执行一次调用者this函数,并且调用者为context起到改变this指向的目的,再处理下参数的传递即可

实现apply

Function.prototype.myApply = function(context){
    if(typeof this != 'function')
      throw new Error('type Error');
    context = context || window;
    context.fn = this
    let ans = arguments[1]?context.fn(...arguments[1]):context.fn();//判断是否传值
    delete context.fn;
    return ans;
  }
  function fn(name, age) {
    this.name = name;
    this.age = age;
  }
  let obj = {
    name: 'gogo'
  }
  fn.myApply(obj,['han',14]);
  console.log(obj.name, obj.age);//han 14

与call不同的是apply传输的是数组。核心是想办法把接受到的数组解构出去。此时slice不能用的原因是传入的是arguement中一个是this,一个数组,解构后还是数组,也就是说到时候传过去还是数组,虽然可以接收的时候用赋值运算符解构,但是这显然不是原生的apply的效果

apply实现bind

Function.prototype.myBind = function(context){
    context = context || window;//保存住原始的改变this的目标context
    let fn = this;//保存初始调用者函数
    let args = [...arguments].slice(1)//保存住原始的传过来的参数

    return function Fn(){
      return fn.apply(this instanceof fn?this:context,args.concat(...arguments))
    }
  }

其中fn.apply(this instanceof fn?this:context,args.concat(…arguments))

  1. fn为刚开始的调用者,改变目标函数不能变
  2. this instanceof fn?this:context:因为bind返回值是一个函数,所以后面可能有调用者,如果没有则更改的this还是前面的context
  3. args.concat(…arguments)):因为后面的时候还可能传参,一块放进去
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值