美文网首页
对JavaScript中apply call bind函数的理解

对JavaScript中apply call bind函数的理解

作者: Bury丶冬天 | 来源:发表于2019-08-01 16:29 被阅读0次
    • apply
      apply函数原理(自定义实现)
    Function.prototype.myapply = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('not funciton')
      }
      context = context || window
      // this 指函数 printA  将 printA 挂载到传入的变量 a 上去
      context.fn = this
      let result
      if (arguments[1]) {
        // 有参数的情况
        // 用 a.fn 执行  相当于 a.printA() 执行函数
        // 由于 apply 是以数组的形式传递被执行函数的所有参数  所以 arguments[1] 是一个数组
        result = context.fn(...arguments[1])
      } else {
        // 无参的情况  直接执行
        result = context.fn()
      }
      // 最后 把临时 变量 (函数fn)  从 传入的对象(a) 里边删除
      delete context.fn
      // 返回函数 printA 的执行结果
      return result
    }
    
    const a={
      name:'张三',
      age:23
    }
    
    function printA(p1,p2){
      console.log(this.name)
      console.log(this.age)
      console.log(p1)
      console.log(p2)
    }
    
    printA.myapply(a,['p1','p2'])
    

    输出结果

    张三
    23
    p1
    p2
    
    • call
      call函数原理(自定义实现)
    Function.prototype.mycall = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('not funciton')
      }
      context = context || window
      context.fn = this
    // 由于call对函数参数以变长形式传递,所以可以直接截取从位置1到剩下的arguments数组
      let arg = [...arguments].slice(1)
    // 将arg解构传递到 printA
      let result = context.fn(...arg)
      delete context.fn
      return result
    }
    
    const a={
        name:'张三',
        age:23
    }
    
    function printA(p1,p2){
        console.log(this.name)
        console.log(this.age)
        console.log(p1)
        console.log(p2)
    }
    
    printA.mycall(a,'p1','p2')
    

    输出结果

    张三
    23
    p1
    p2
    

    apply与call的区别

    只在参数的传递方式上存在区别

    1. apply对函数的参数以数组的形式传递
      即 fun.apply(obj,[arg1,arg2,...]) apply函数里边的 arguments.length 长度为1或者2
    2. call对函数的参数以变长参数的形式传递
      即 fun.call(obj,arg1,agr2,...) call函数里边的 arguments.length 长度大于等于1
    • bind
      bind函数原理(自定义实现)
    Function.prototype.mybind = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      let _this = this
      let arg = [...arguments].slice(1)
      // bind函数的执行结果返回一个函数,需要自执行才能真正执行 context(即printA)
      return function F() {
        // 处理函数使用new的情况
        if (this instanceof F) {
          return new _this(...arg, ...arguments)
        } else {
          // return _this.apply(context, arg.concat(...arguments))
          // 或者
          return _this.call(context, ...arg.concat(...arguments))
        }
      }
    }
    
    const a={
      name:'张三',
      age:23
    }
    
    function printA(p1,p2){
      console.log(this.name)
      console.log(this.age)
      console.log(p1)
      console.log(p2)
    }
    
    printA.mybind(a,'p1','p2')()
    

    输出结果

    张三
    23
    p1
    p2
    

    bind基于apply或者call函数实现,函数参数使用可变参数的方式传递

    相关文章

      网友评论

          本文标题:对JavaScript中apply call bind函数的理解

          本文链接:https://www.haomeiwen.com/subject/wmqcdctx.html