改变this指向-call、apply、bind的内部实现

改变this指向-call、apply、bind的内部实现

手写call

    //  call 的内部实现
    Function.prototype.myCall = function(context) {
    
    
      // 判断调用者是否为函数
      if(typeof this !== 'function') {
    
    
        throw new TypeError('Error')
      }
      // 不传参默认为 window
      context = context || window
      // 新增 fn 属性,将值设置为需要调用的函数
      context.fn = this
      // 将arguments 转化为数组将call 的传参提取出来
      const args = Array.from(arguments).slice(1)
      // 传参调用函数
      const result = context.fn(...args)
      // 删除函数
      delete context.fn
      //  返回执行结果
      return result;
    }
    // 普通函数
    function print(age) {
    
    
      console.log(this.name+ " " + age);
    }
    // 自定义对象
    var obj = {
    
    
      name: 'JavaScript'
    }
    // 调用 myCall 方法
    print.myCall(obj, 1,2,3) // JavaScript 1

手写apply

    // apply 内部实现
    Function.prototype.myApply = function(context) {
    
     
      // 判断调用者是否为函数 
      if(typeof this !== 'function') {
    
     
        throw new TypeError('Error')
      }
        // 不传参默认为 window 
        context = context || window 
        // 新增 fn 属性,将值设置为需要调用的函数 
        context.fn = this 
        // 返回执行结果 
        let result; 
        // 判断是否有参数传入 
        if(arguments[1]) {
    
     
          result = context.fn(...arguments[1]) 
        }else {
    
    
          result = context.fn() 
        }
        // 删除函数 
        delete context.fn 
        // 返回执行结果 
        return result; 
      }
        // 普通函数 
        function print(age,age2,age3) {
    
     
          console.log(this.name+" "+ age + " "+ age2+" "+age3); 
        }
        // 自定义对象 
        var obj = {
    
     name:'js' }
        // 调用函数的 call 方法 
        print.myApply(obj,[1,2,3]) // js 1 2 3

手写bind

     Function.prototype.myBind = function (context) {
    
    
          // 判断调用者是否为函数
          if(typeof this !== 'function') {
    
    
            throw new TypeError('Error')
          }
          // 截取传递的参数
          const args = Array.from(arguments).slice(1)
          // _this 指向调用的函数
          const _this = this;
          // 返回一个函数
          return function F() {
    
    
            // 因为返回了一个函数,我们可以new F(), 所以需要判断
            // 对于new 的情况来说,不会被任何方式改变 this
            if(this instanceof F) {
    
    
              return new _this(...args, ...arguments)
            } else {
    
    
              return _this.apply(context, args.concat(...arguments))
            }
          }
        }
        // 普通函数
        function print3(age,age2,age3) {
    
    
          // new 的方式调用 bind 参数输出换做 [...arguments]
          console.log(this.name+" "+ age + " "+ age2+" "+age3);
        }
        // 自定义对象
        var obj = {
    
    
          name: 'myBind'
        }
        // 调用函数的 call 方法
        let F = print3.myBind(obj,1,2,3);
        F() // myBind 1 2 3
        // 返回对象
        let obj1 = new F();
        console.log(obj1); // undefined 1 2 3

三者区别

参数

  • 第一个参数:都是this要指向的对象

  • 第二个参数:

    call->参数可用逗号分隔, 也可传数组

    apply->必须放在数组里面传进去

    bind->参数可用逗号分隔, 也可传数组

返回值

bind返回值为一个新的函数,其余返回结果都一致

猜你喜欢

转载自blog.csdn.net/qq_46178261/article/details/112305557