深入理解call、apply、bind等及手写实现

part0前言

这三种方式 不管是哪一种其实都是通过复制目标属性并将调用目标的方法实现。

比如这个应用场景:

对象调用Array的sort方法==》Array.sort(obj)

part1  call

///call  bind  apply的应用
  ///call 
  let PeoSon = {
    name: "里",
    say(param) {
      console.log(this);
      console.log(`我是${this.name}`)
 console.log(`我是${param}`)
    }
  }
  PeoSon1 = {
    name: "整"
  }
  // Function.prototype.MyCall = function (context) {
  //   ///这里的办法是重新覆盖上去
  //   //context就是demo中的Person1
  //   // 必须此时调用MyCall的函数是say方法,那么我们只需要在context上扩展一个say方法指向调用MyCall的say方法这样this
  //   debugger
  //   console.log(this)
  //   context.say = this //Mycall里边的this就是我们虚拟的say方法
  //   console.log(context)
  //   context.say()
  // }
  //PeoSon.say.call(PeoSon1)
  // PeoSon.say.MyCall(PeoSon1)
  /**
   * 实现call的方式是覆盖
   * 我们在 .MyCall的时候
   * 将上下文传入=》即对象传入等待拓展
   * 传入后拓展要覆盖的方法=》say
   **/
  Function.prototype.myCall = function (context) {
    context.say = this;
    context.say()
  }
  改进1、call支持多个参数,有可能一个也不没有 
  Function.prototype.myCall1 = function (context) {
    context = context || window
    context.say = this;
    context.say()
  }
  // 改进2、 考虑多参数时要把参数传给扩展方法。
  // 改进3、 给上下文定义的函数要保持唯一不能是say
  // 改进4、 扩展完我们需要吧自定义函数删除 
  Function.prototype.myCall2 = function (context) {
    context = context || window;
    //给上下文定义的函数要保持唯一不能是say
    let fn = mySymbol(context);
    context[fn] = this;
    //考虑多参数时要把参数传给扩展方法。
    let arg = [...arguments].slice(1);//除了复制目标对象外的所有参数
    context[fn](..arg);
    delete context[fn];
  }
  ///自定义Symbol方法 得到唯一值
  mySymbol = function (obj) {
    let unique = (Math.random() + new Date().getTime()).toString(32).slice(0, 8);
    if (obj.hasOwnProperty(unique)) {
      mySymbol(unique);
    } else {
      return unique
    }
  }

  let PeoSon3 = {
    name: "里",
    age: 18,
    say() {
      console.log(this);
      console.log(`我是${this.name} +++ ${this.age}`)
    }
  }
  PeoSon4 = {
    name: "整 ",
    age: 20,
  }
  PeoSon3.say.myCall2(PeoSon4)

part2 apply

类似call

part3 bind

bind的方式与apply/call不同==》这个函数要支持柯里化的!

  let Peoson = {
    name: "人",
    say(param) {
      console.log(`${this.name}`)
      console.log(`${param}`)
    },
    hello() {
      alert("hello")
    }
  }
  let Chinese = {
    name: "中国人"
  }
  // Peoson.say.bind(Chinese);
  // bind
  Function.prototype.bind = function (context) {
    let self = this;
    let arg = [...arguments].slice(1)
    return function () {
      let newArg = [...arguments]
      self.apply(context, arg.concat(newArg))
    }
  }
  let fn = Peoson.say.bind(Chinese, "123");
  fn();

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值