手写call

Function.prototype.myCall = function (ctx, ...args) {
  // 参数归一化
  ctx = ctx === undefined || ctx === null ? globalThis : Object(ctx)
 
  // 拿到要执行的函数
  const fn = this
 
  // 绑定函数到ctx,(优化:不能被遍历到)
  const key = Symbol("function_call")
  Object.defineProperty(ctx, key, {
    value: fn,
    enumerable: false,
  })
 
  // 执行函数并返回对应的结果
  const result = ctx[key](...args)
  delete ctx[key]
  return result
}
 
function test(a, b) {
  console.log(this, a, b, this.name)
  return a + b
}
 
console.log(test.myCall({ name: "tttt" }, 1, 3))
 

手写bind

Function.prototype.myBind = function (ctx, ...args) {
  // 要执行的函数
  const fn = this
 
  return function A(...rest) {
    // 如果是 new 调用的,保留new的行为
    if (Object.getPrototypeOf(this) === A.prototype) {
      // 或者 this instanceof A
      return new fn(...args, ...rest)
    }
 
    // 执行函数并返回结果
    return fn.apply(ctx, [...args, ...rest])
  }
}
 
function test(a, b, c, d) {
  console.log(this, a, b, c, d)
  return a + b
}
 
const newFn = test.myBind({ name: "aa" }, 1, 2)
console.log(newFn(3, 4))
console.log(new newFn(3, 4))