TypeScript深度克隆动态生成对象时返回空对象的异常问题排查
TypeScript深度克隆动态生成对象时返回空对象的异常问题排查
嘿,这个问题看起来挺诡异的,但其实根源就在你创建facetValues对象的方式上!我来给你拆解清楚:
问题核心原因
你用Object.defineProperty给facetValues添加属性的时候,没有设置enumerable: true,而这个属性的默认值是false——也就是说,你添加的status、plan这些属性都是不可枚举的!
而你用到的两种克隆方式:lodash的_cloneDeep和JSON.parse(JSON.stringify()),都是依赖对象的可枚举属性来完成复制的。它们会跳过不可枚举的属性,自然就返回空对象了。
至于为什么console.log(fullValues)能显示出这些属性?那是因为浏览器控制台会展示对象的所有属性(包括不可枚举的),这很容易给人造成“属性正常”的错觉,但克隆工具可不认这个。
对比验证
你后面用字面量直接创建的对象:
let fullValues: { [key : string ] : Array<string> } = { status: [], plan: [] };
这里的属性默认是可枚举的,所以克隆工具能正常识别,自然就返回正确的结果了。
解决方案
有两种简单的修复方式:
1. 给Object.defineProperty添加enumerable: true配置
修改你创建facetValues的代码:
const facetValues: { [key: string]: Array<string> } = {}; if (facetedData) { Object.entries(facetedData).forEach(([key, value]) => { Object.defineProperty(facetValues, key, { value: [] as string[], enumerable: true // 关键:显式设置属性可枚举 }); }); }
2. 直接赋值创建属性(更简洁)
其实完全没必要用Object.defineProperty,直接给对象赋值就能创建可枚举属性:
const facetValues: { [key: string]: Array<string> } = {}; if (facetedData) { Object.entries(facetedData).forEach(([key]) => { facetValues[key] = []; // 直接赋值,属性默认可枚举 }); }
修改之后,你再用_cloneDeep或者JSON方法克隆,就能得到包含所有属性的对象啦!
备注:内容来源于stack exchange,提问作者mani-hash
相关产品推荐
相关产品推荐

