手写一个函数,将任意函数转换为 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
}实际应用
- React 早期(class 组件)在 constructor 中
this.handleClick = this.handleClick.bind(this)就是 hardBind 的应用 Function.prototype.bind的原生实现就是这种模式