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

TypeScript中如何克隆带有动态定义属性的对象?

为什么克隆后的对象没触发setter?怎么解决?

这个问题我之前也踩过坑,核心原因是你用的Object.assign()并不适合克隆带getter/setter这类特殊属性的对象——它只会遍历源对象的自身可枚举属性,把属性值直接复制到目标对象上,完全忽略了属性的描述符(比如get、set、configurable这些配置项)。所以你克隆出来的s对象里,name只是个普通字符串属性,和原对象的get/set逻辑完全脱节,自然不会触发alert。

不用循环的解决方案:基于属性描述符克隆

你可以用Object.getOwnPropertyDescriptors()和Object.create()组合实现,这两个方法能完整保留原对象的属性描述符,包括getter和setter,而且不需要手动循环:

class User{ name:string= "" }
var t = new User();
var obj = {}
Object.defineProperty(obj, 'name', {
 get(){ return t.name; },
 set(value: string){ t.name= value; alert("name is set") },
 configurable : true
});

// 第一步:获取原对象所有自身属性的完整描述符
const propDescriptors = Object.getOwnPropertyDescriptors(obj);
// 第二步:创建新对象,继承原对象的原型,并应用所有属性描述符
const s = Object.create(Object.getPrototypeOf(obj), propDescriptors);

// 现在赋值会正常触发alert了
s.name = "alen";

原理说明

  • Object.getOwnPropertyDescriptors(obj):返回一个对象,包含obj所有自身属性的完整配置信息(包括get、set、enumerable、configurable等),而不是只返回属性值。
  • Object.create(proto, descriptors):第一个参数指定新对象的原型(保证原型链和原对象一致),第二个参数直接传入刚才获取的描述符对象,这样新对象的每个属性都会按照原对象的配置定义,自然保留了getter和setter的逻辑。

这样既不用手动循环定义属性,又能完美克隆带有动态属性(get/set)的对象。

内容的提问来源于stack exchange,提问作者Alen.Toma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:44:07