手写call、apply、bind方法

call、apply、bind 都是为了改变函数运行时上下文(this指向)而存在的。

它们有什么不同?

  • 它们接收的第一个参数都是函数上下文也就是要绑定的this指向。
  • apply的第二个参数是一个参数数组,call和bind的第二个及之后的参数作为函数实参按顺序传入。
  • bind绑定完this的指向后会返回一个新的函数体,不会被立即调用,其他两个会立即调用。

实现call方法

Function.prototype.myCall = function(thisObj,...args){
   if(typeof this !== 'function') { // this 必须是函数
     throw new TypeError(`It's must be a function`)
   }
   thisObj = thisObj || window
   let fn = Symbol()
   thisObj[fn] = this
   let res =  thisObj[fn](...args)
   delete thisObj[fn]
   return res
}

 

实现apply方法

Function.prototype.myApply = function(thisObj,args=[]){
   if(typeof this !== 'function') { // this 必须是函数
     throw new TypeError(`It's must be a function`)
   }
   thisObj = thisObj || window
   let fn = Symbol()
   thisObj[fn] = this
   let res =  thisObj[fn](...args)
   delete thisObj[fn]
   return res
}

 

实现bind方法

Function.prototype.myBind = function (thisObj, ...args) {
  const fn = this
if(typeof fn !== 'function'){ throw new TypeError('It must be a function') }
  thisObj = thisObj || window
  return function (...otherArgs) { 
return fn.apply(thisObj, [...args, ...otherArgs])
}
}

 如果要支持new:

Function.prototype.myBind = function (thisObj, ...args) {
    var fn= this
    if(typeof fn !== 'function'){
        throw new TypeError('It must be a function')
    }
    thisObj = thisObj || window
    // new优先级
    var result = function () {
        return fn.apply(this instanceof result ? this : thisObj, args.concat(Array.prototype.slice.call(arguments)))
    }
    // 继承原型上的属性和方法
    result.prototype = Object.create(fn.prototype)
    return result
}

 

posted @ 2020-12-16 20:44  奥利奥ALA  阅读(145)  评论(0)    收藏  举报