JavaScript 手写call、apply、bind

51 阅读1分钟

call、apply、bind都是用来改变this指向的,区别在于call和apply是立即执行的,而bind需要再次调用。

call

Function.prototype.myCall = function(context){
    //先判断调用myCall是不是一个函数
    //这里的this就是调用myCall的
    if(typeof this !== 'function'){
        throw new TypeError('Not a Function')
    }
    
    //不传参数默认为window
    context = context||window
    
    //保存this
    context.fn = this
    
    //保存参数
    const args = [...arguments].slice(1) //当一个参数为context,去除
    
    //调用函数
    const result = context.fn(...args)
    
    delete context.fn
    
    return result
}

apply

//apply
Function.prototype.myApply = function (context) {
      // 判断this是不是函数
      if (typeof this !== "function") {
        throw new TypeError("Not a Function")
      }

      let result

      // 默认是window
      context = context || window

      // 保存this
      context.fn = this

      // 是否传参
      if (arguments[1]) {
        result = context.fn(...arguments[1])
      } else {
        result = context.fn()
      }
      delete context.fn

      return result
    }

bind

    Function.prototype.myBind = function(context){
      // 判断是否是一个函数
      if(typeof this !== "function") {
        throw new TypeError("Not a Function")
      }
      // 保存调用bind的函数,返回一个绑定this的函数
      const _this = this 
      // 保存参数
      const args = [...arguments].slice(1)
      // 返回一个函数
      return function F () {
        // 判断是不是new出来的
        if(this instanceof F) {
          // 如果是new出来的
          // 返回一个空对象,且使创建出来的实例的__proto__指向_this的prototype,且完成函数柯里化
          return new _this(...args,...arguments)
        }else{
          // 如果不是new出来的改变this指向,且完成函数柯里化
          return _this.apply(context,args.concat(...arguments))
        }
      } 
    }