You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

派生类构造函数中Proxy方法里的`this`为何为undefined?

继承类中使用Proxy代理方法时this为undefined的问题及解决方案

场景描述

尝试通过继承类并为方法定义Proxy对象,来覆盖/代理一个库类的函数。但派生类中的this对象为undefined,且现有解决方案因Proxy的使用无法生效。

示例代码

class Structure {
    constructor (name){
        this.noDoors = 0
        this.name = name
    }
    async addDoors(noDoorsToAdd){
        this.noDoors += noDoorsToAdd
        console.log(`${noDoorsToAdd} doors added to ${this.name}`)
        return new Promise(r=>r())
    }
}

const Building = class Building extends Structure {
    constructor(conditionfunc,args){
        super(args)     

        this.addDoors = new Proxy(this.addDoors, {
            apply(target, thisArg, argumentsList){
                //console.log("apply:",target, thisArg, argumentsList,conditionfunc(argumentsList[0]))
                if (conditionfunc(argumentsList[0])){
                    console.log(`Correct password: About to add doors to ${thisArg.name}`)
                    target(argumentsList[1]);
                }
                else {
                    console.log(`Incorrect password: Doors not added to ${thisArg.name}`)
                }
            }
        })
    }
}


/******** Main Script *********/

let conditionfunc = (password) => {
    if (password == '123456') { return true } else {return false }
}

 myStructure = new Structure('Ty Bach')
 myBuilding = new Building(conditionfunc,'Ty Mawr')

 ;(async()=>{
  await myStructure.addDoors(1)
    await myBuilding.addDoors('wrongpassword',7)
    await myBuilding.addDoors('123456',4)
  
  console.log(`${myStructure.name} has ${myStructure.noDoors} doors!`)
    console.log(`${myBuilding.name} has ${myBuilding.noDoors} doors!`)
})();

预期与实际结果

预期myBuilding对象最终会有4个门,但控制台报错如下:

1 doors added to Ty Bach
Doors not added to Ty Mawr
About to add doors to Ty Mawr
Ty Bach has 1 doors!
Ty Mawr has 0 doors!
(node:3732) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'noDoors' of undefined
    at addDoors (MYPATH\proxytoy\test.js:11:3)
    at Object.apply (MYPATH\proxytoy\test.js:26:6)
    at MYPATH\proxytoy\test.js:51:23
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:3732) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:3732) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

问题

  1. 派生类对象中this为何为undefined?
  2. 如何修复该问题,或通过其他方式实现相同需求?

解答

问题1:this为undefined的原因

直接调用target(argumentsList[1])时,没有给原方法addDoors绑定正确的上下文。类的实例方法的this依赖于调用时的上下文,这里直接调用target(原addDoors函数)属于独立调用状态,而类内部方法默认运行在严格模式中,此时this会被设为undefined,因此触发报错。另外,原方法是async函数,调用时未返回Promise,也导致了未处理的Promise拒绝警告。

问题2:修复方案及替代实现

方案1:修复Proxy中的方法调用

在Proxy的apply陷阱里,使用call或apply给原方法绑定正确的上下文thisArg,同时正确传递参数并返回Promise:

const Building = class Building extends Structure {
    constructor(conditionfunc, args) {
        super(args)     

        this.addDoors = new Proxy(this.addDoors, {
            async apply(target, thisArg, argumentsList) {
                if (conditionfunc(argumentsList[0])) {
                    console.log(`Correct password: About to add doors to ${thisArg.name}`)
                    // 绑定上下文并传递参数,返回原方法的Promise
                    return target.call(thisArg, argumentsList[1]);
                } else {
                    console.log(`Incorrect password: Doors not added to ${thisArg.name}`)
                    // 返回空Promise避免未处理拒绝
                    return Promise.resolve();
                }
            }
        })
    }
}

方案2:不使用Proxy,直接重写方法

若不需要Proxy的额外特性,直接在派生类中重写addDoors方法更直观:

const Building = class Building extends Structure {
    constructor(conditionfunc, args) {
        super(args)
        this.conditionfunc = conditionfunc;
    }

    async addDoors(password, noDoorsToAdd) {
        if (this.conditionfunc(password)) {
            console.log(`Correct password: About to add doors to ${this.name}`)
            // 调用父类方法并绑定当前实例上下文
            return super.addDoors(noDoorsToAdd);
        } else {
            console.log(`Incorrect password: Doors not added to ${this.name}`)
            return Promise.resolve();
        }
    }
}

两种方案都能解决this的问题,最终myBuilding的noDoors会正确更新为4。


内容的提问来源于stack exchange,提问作者Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:30:58