旧文传送门:浅谈apply、call、bind及其ES6手写实现

Function.prototype.apply

apply - MDN

call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

TypeScript定义
/**
 * Calls the function with the specified object as the this value and the elements of specified array as the arguments.
 * @param thisArg The object to be used as the this object.
 * @param args An array of argument values to be passed to the function.
 */
apply<T, R>(this: (this: T) => R, thisArg: T): R;
apply<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, args: A): R;
手写实现
interface Function {
  myApply: Function
}
Function.prototype.myApply = function(context: any, args?: any[]) {
  if (typeof context !== 'object') {
      throw Error()
  }
  const symbol = Symbol()
  context[symbol] = this
  const res = args ? context[symbol](...args) : context[symbol]()
  delete context[symbol]
  return res
}

Function.prototype.call

call - MDN

TypeScript定义
/**
 * Calls the function with the specified object as the this value and the specified rest arguments as the arguments.
 * @param thisArg The object to be used as the this object.
 * @param args Argument values to be passed to the function.
 */
call<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, ...args: A): R;
手写实现
interface Function {
  myCall: Function
}
Function.prototype.myCall = function (context: any, ...args: any[]) {
  if (typeof context !== 'object') {
    throw Error()
  }
  const symbol = Symbol()
  context[symbol] = this
  const res = context[symbol](...args)
  delete context[symbol]
  return res
}

Function.prototype.bind

bind - MDN

TypeScript定义
/**
 * For a given function, creates a bound function that has the same body as the original function.
 * The this object of the bound function is associated with the specified object, and has the specified initial parameters.
 * @param thisArg The object to be used as the this object.
 * @param args Arguments to bind to the parameters of the function.
 */
bind<T>(this: T, thisArg: ThisParameterType<T>): OmitThisParameter<T>;
bind<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R;
bind<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R;
bind<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
bind<T, A0, A1, A2, A3, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R;
bind<T, AX, R>(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R;
手写实现
interface Function {
  myBind: Function
}

Function.prototype.myBind = function (context: any, args1?: any[]) {
  if (typeof context !== 'object') {
    throw Error()
  }
  return (...args2: any[]) => {
    if (!args1) {
      return this.myApply(context, args2)
    }
    return this.myApply(context, args1.concat(args2))
  }
}

其他