可利用Object.getOwnPropertyDescriptor获取方法描述符并提取value函数,再通过bind/call/apply重绑定this,最后用Object.defineProperty将新函数定义到目标对象以保持属性特性。

可以利用 Object.getOwnPropertyDescriptor 获取方法的属性描述符(尤其是 value),再结合 bind、call 或箭头函数重绑定,实现运行时动态迁移方法的执行上下文(即改变 this 指向)。关键在于:先“读取”原方法的定义,再“重新挂载”到目标对象上,同时确保其行为与原始语义一致。
获取方法描述符并提取可调用函数
使用 Object.getOwnPropertyDescriptor 读取源对象上方法的完整描述符。若该方法是数据属性(常见于普通函数赋值),则 descriptor.value 就是函数本身;若为访问器属性,则需通过 get 或 set 获取逻辑。
- 确保目标属性存在且为
configurable: true,否则无法修改或重新定义 - 注意区分
value和get:类方法通常落在value上,而 getter/setter 需单独处理 - 示例:
const desc = Object.getOwnPropertyDescriptor(src, 'methodName');,之后检查desc && desc.value instanceof Function
创建新上下文绑定的函数
拿到原始函数后,用 bind 创建绑定新 this 的版本,或在调用时用 call/apply 动态指定。若需保留原型链或支持 new 调用,避免直接 bind(会丢失 constructor),改用包装函数。
-
const boundFn = desc.value.bind(targetContext);最简方式,适合普通调用 - 需要兼容构造调用时:
function wrapper(...args) { return desc.value.apply(targetContext, args); } - 若原方法依赖闭包或私有变量,确保迁移后仍能访问——这要求原始函数本身不强耦合源对象的私有状态
将绑定后的函数定义到目标对象
用 Object.defineProperty 将新函数作为数据属性写入目标对象。可复用原描述符的 enumerable、writable、configurable 等元信息,保持行为一致性。
- 推荐复制原描述符,仅替换
value:Object.defineProperty(target, 'methodName', { ...desc, value: boundFn }); - 若目标对象已有同名属性,先检查
configurable是否允许覆盖,否则需先delete或使用Object.assign替代(但会丢失属性特性) - 注意:不能直接赋值(如
target.methodName = boundFn),否则会丢失enumerable等特性,且无法控制writable
处理访问器属性和继承方法
若原方法来自原型链(如 Array.prototype.map),需先用 Object.getPrototypeOf 找到定义它的对象,再获取描述符。对于访问器(get/set),不能只绑定 value,而应重新定义整个访问器,并在内部调用原始 get 或 set 时传入新上下文。
- 获取原型上的方法:
const proto = Object.getPrototypeOf(src); const desc = Object.getOwnPropertyDescriptor(proto, 'methodName'); - 迁移 getter:
{ get() { return originalGet.call(targetContext); }, enumerable: desc.enumerable, configurable: desc.configurable } - 若方法被
Object.freeze或Object.seal,需提前解除限制,或改用代理(Proxy)间接拦截

















