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
相关产品推荐
相关产品推荐

