39.详解call,apply,bind

46 阅读1分钟

前几章有讲到this指向的问题,我们改变this指向有call,apply,bind三种方法,这三种方法都是挂载在原型链上的3个方法.今天这一章就来具体的学习一下.和Promise一样,我觉得手写是最能理解的方式之一.

call

有多个参数,第一个是函数的this,后面是你所需要传递的参数,会直接调用函数

    // 挂载在函数的原型上
    Function.prototype.MyCall = function (thisArg, ...args) {
      //this指的是当前函数
      let fn = this
      // 判断传入的this是什么
      thisArg = (thisArg === undefined || thisArg === null) ? window : Object(thisArg)
      thisArg.fn = fn
      //如果arg不存在,就将其设置为[],方便结构
      args = args || []
      let res = thisArg.fn(...args)
      //执行完之后就删除该对象上的属性
      delete thisArg.fn
      return res
    }
    function fn () {
      console.log(this);
    }
    fn.MyCall({a:1}) // {a:1}

apply

apply]2个参数,第一个是函数的this,第二个是参数的数组,会直接调用

    Function.prototype.MyApply = function (obj, arg) {
      let fn = this //this表示函数
      // 如果要是obj为undefined或者null时,设置其为window,
      // 如果是基本数据类型,则将其设置为对象类型
      let thisArg = (obj === undefined || obj === null) ? window : Object(obj)
      thisArg.fn = fn
      arg = arg || [] //如果arg不存在,则直接赋值为[]
      let res = thisArg.fn(...arg)
      delete thisArg.fn
      return res
    }

bind

和call一样 但是不调用

    Function.prototype.MyBind = function (obj, ...args1) {
      let fn = this
      let thisArg = (obj === undefined || obj === null) ? window : Object(obj)

      return function (...args2) {
        thisArg.fn = fn
        let args = [...args1, ...args2]
        let result = thisArg.fn(...args)
        delete thisArg.fn
        return result
      }
    }