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

如何让类方法返回对象的函数正确绑定自身this以修改属性?

问题描述

我有一个包含两个方法的类:

  • 对象工厂方法objFactory:返回包含三个属性(value1、value2、value3)和一个绑定函数的对象,示例如myObj = {value1: 1, value2: 2, value3: 3, func()}
  • 类方法changeValueProperties:根据输入值为返回对象生成value1-3的值

要求用户不得直接修改返回对象的value1-3属性,必须通过调用内置方法更新,changeValueProperties对用户是黑盒,无需知晓计算逻辑。

核心问题是this指向:当前this指向MyTestClass实例,而我需要它指向返回的对象以修改其内部属性。我知道可以用call/apply/bind方法,但不清楚该场景下的具体操作,尤其是updateValues还要调用类自身的方法进行计算。

也接受架构层面的替代建议,我清楚当前实现可能不够规范,希望有更优方案。

附当前代码:

class MyTestClass {
    dummyData;
    constructor() {
        this.dummyData = 100;
    }
    changeValueProperties(value) {
        return {
            value1: value*1,
            value2: value*2,
            value3: value*3
        }
    }

    objFactory(value, ...otherParameters) {
        
        let computedValues = this.changeValueProperties(value);

        let updateValues = (newValue) => {
            let computedValues = this.changeValueProperties(newValue);
            // 此处需要更新返回给用户的myReturnedObj里的value1-3
            // this指向MyTestClass而非myReturnObj,因此下面的代码无效
            this.value1 = computedValues.value1;
            this.value2 = computedValues.value2;
            this.value3 = computedValues.value3;

        }

        let myReturnObj = {
            value1: computedValues.value1,
            value2: computedValues.value2,
            value3: computedValues.value3,
            updateValues: updateValues
        }
        return myReturnObj
    }

}

const myClass = new MyTestClass();

let myObj = myClass.objFactory(10,...otherParameters for object generation); 
// 期望得到 {value1: 10, value2: 20, value3: 30, ...}
myObj.updateValues(20); 
// 期望更新后得到 {value1: 20, value2: 40, value3: 60, ...}
解决方案

方案一:利用闭包直接修改返回对象

updateValues定义在objFactory内部,可通过闭包直接访问并修改返回对象的属性,无需处理this绑定问题:

class MyTestClass {
    dummyData;
    constructor() {
        this.dummyData = 100;
    }
    changeValueProperties(value) {
        return {
            value1: value*1,
            value2: value*2,
            value3: value*3
        }
    }

    objFactory(value, ...otherParameters) {
        
        let computedValues = this.changeValueProperties(value);

        let myReturnObj = {
            value1: computedValues.value1,
            value2: computedValues.value2,
            value3: computedValues.value3,
            updateValues: (newValue) => {
                let newComputed = this.changeValueProperties(newValue);
                // 通过闭包直接修改返回对象的属性
                myReturnObj.value1 = newComputed.value1;
                myReturnObj.value2 = newComputed.value2;
                myReturnObj.value3 = newComputed.value3;
                // 可选:返回更新后的对象
                return myReturnObj;
            }
        }
        return myReturnObj
    }

}

const myClass = new MyTestClass();
let myObj = myClass.objFactory(10);
console.log(myObj); // {value1:10, value2:20, value3:30, updateValues: ƒ}
myObj.updateValues(20);
console.log(myObj); // {value1:20, value2:40, value3:60, updateValues: ƒ}

如果需要严格限制用户直接修改属性,可通过Object.defineProperty将value1-3设为不可写:

let myReturnObj = {};
// 定义只读属性
Object.defineProperty(myReturnObj, 'value1', {
    value: computedValues.value1,
    writable: false,
    enumerable: true
});
Object.defineProperty(myReturnObj, 'value2', {
    value: computedValues.value2,
    writable: false,
    enumerable: true
});
Object.defineProperty(myReturnObj, 'value3', {
    value: computedValues.value3,
    writable: false,
    enumerable: true
});

// updateValues中重新定义属性实现更新
updateValues: (newValue) => {
    let newComputed = this.changeValueProperties(newValue);
    Object.defineProperty(myReturnObj, 'value1', { value: newComputed.value1, writable: false, enumerable: true });
    Object.defineProperty(myReturnObj, 'value2', { value: newComputed.value2, writable: false, enumerable: true });
    Object.defineProperty(myReturnObj, 'value3', { value: newComputed.value3, writable: false, enumerable: true });
    return myReturnObj;
}

此时用户直接修改myObj.value1 = 100会失效,必须通过updateValues方法更新。

方案二:用内部类封装返回对象(更规范的架构)

若追求更严谨的面向对象设计,可将返回对象封装为内部类,this指向更清晰,封装性更强:

class MyTestClass {
    dummyData;
    constructor() {
        this.dummyData = 100;
    }

    // 私有内部类,用于创建返回对象
    #InnerObj = class {
        #parent; // 持有外部类引用,用于调用changeValueProperties
        #value1;
        #value2;
        #value3;

        constructor(parent, initialValue) {
            this.#parent = parent;
            const computed = parent.changeValueProperties(initialValue);
            this.#value1 = computed.value1;
            this.#value2 = computed.value2;
            this.#value3 = computed.value3;
        }

        // 提供getter让用户读取属性,无法直接修改
        get value1() { return this.#value1; }
        get value2() { return this.#value2; }
        get value3() { return this.#value3; }

        updateValues(newValue) {
            const computed = this.#parent.changeValueProperties(newValue);
            this.#value1 = computed.value1;
            this.#value2 = computed.value2;
            this.#value3 = computed.value3;
            return this;
        }
    }

    changeValueProperties(value) {
        return {
            value1: value*1,
            value2: value*2,
            value3: value*3
        }
    }

    objFactory(value, ...otherParameters) {
        return new this.#InnerObj(this, value);
    }
}

const myClass = new MyTestClass();
let myObj = myClass.objFactory(10);
console.log(myObj.value1); // 10
myObj.updateValues(20);
console.log(myObj.value1); // 20

该方案优势:

  • updateValues中的this自然指向内部类实例(即返回给用户的对象)
  • 私有字段#parent、#InnerObj、#value1-3隐藏内部细节,符合封装原则
  • 用户只能通过getter读取属性,无法直接修改,完全满足需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:55:19