手写一个函数,将任意函数转换为 this 永远绑定的版本

这是一个增强版 bind,确保即使在后续被 call/apply 或作为方法调用时,this 仍然不变:

function hardBind(fn, ctx) {
  const bound = function (...args) {
    return fn.apply(ctx, args)
  }
  // 让 bound 的原型指向 fn 的原型,支持 new
  Object.setPrototypeOf(bound, fn)
  return bound
}

// 测试
function greet(greeting) {
  console.log(greeting + ', ' + this.name)
}
const person = { name: 'Tom' }
const bound = hardBind(greet, person)

bound('Hi')                    // 'Hi, Tom'
bound.call({ name: 'Jerry' }, 'Hello')  // 'Hi, Tom'(this 不变)

进阶版:支持 new 调用

function hardBind(fn, ctx, ...presetArgs) {
  const bound = function (...args) {
    // 如果是 new 调用,this 指向新实例,不用 ctx
    return fn.apply(
      this instanceof bound ? this : ctx,
      [...presetArgs, ...args]
    )
  }
  // 维持原型链
  bound.prototype = Object.create(fn.prototype)
  return bound
}

实际应用

同分类其他题目