1. 程式人生 > 實用技巧 >手寫call、apply、bind方法

手寫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
}