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

TypeScript类箭头函数经扩展语法浅克隆后读取旧值问题求助

问题根本原因
  1. 你在类中使用箭头函数定义类属性方法的写法,会让该方法的this在类实例化时就固定绑定到当前创建的实例,不会随调用对象变化而改变。
  2. {...bob} 扩展运算符和Object.assign都是浅拷贝逻辑,只会复制源对象自身的可枚举属性,包括已经绑定了旧实例this的bark方法,拷贝得到的新对象上的bark方法仍然绑定旧实例bob的上下文,因此读取的还是旧实例的name属性。
  3. 额外补充:如果你用普通原型方法定义类函数,扩展运算符也不会拷贝原型链上的方法,新对象调用该方法会直接报错。react-data-grid做数据更新时默认采用immutable方式生成新普通对象,不会保留原类实例的原型链和方法绑定关系,这是问题的核心诱因。
可行解决方案

你可以根据自己的业务场景选择以下任意一种方案:

  • 方案1:改用普通原型方法,手动维护实例原型
    把类中的箭头函数方法改成普通原型方法,生成新对象时用Object.create绑定原类原型,再赋值属性:

    class Dog {
        name: string;
        // 改为普通原型方法,this随调用对象动态绑定
        bark():string {
            return "hi, I am " + this.name;
        }
    
        constructor(name: string) {
            this.name = name;
        }
    }
    
    let bob = new Dog('bob');
    // 创建新对象时先绑定原型,再合并属性
    const jill = Object.assign(Object.create(Dog.prototype), bob, {name: 'jill'});
    console.log(jill.bark()); // 输出 hi, I am jill
    

    该方案适合类构造函数无额外初始化逻辑的场景,改动量小。

  • 方案2:每次数据更新时重新实例化类
    不管是你自己更新数据,还是从react-data-grid拿到变更后的行数据,都重新用new关键字创建类实例,确保方法和上下文绑定正确:

    const jill = new Dog('jill');
    console.log(jill.bark()); // 输出 hi, I am jill
    

    如果是配合react-data-grid使用,可以在给组件传rows参数前,先把所有行数据遍历一遍重新实例化你的Row类,也可以用库提供的行数据转换钩子处理。

  • 方案3:改为接收实例作为参数的独立函数
    放弃把方法挂载到类上,直接定义独立的工具函数,接收类实例作为入参,完全规避this绑定问题,该方案最适配React生态的immutable数据流设计:

    function bark(dog: Dog) {
      return "hi, I am " + dog.name;
    }
    
    const jill = {...bob, name: 'jill'};
    console.log(bark(jill)); // 输出 hi, I am jill
    

    该方案无需处理类实例和原型逻辑,稳定性最高,推荐优先选用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:36:05