如何高效将对象拆分映射至多个目标对象?ES8方案咨询
问题:拆分inputData属性到对应类实例的最优实现方式?
我需要将如下结构的inputData对象属性拆分至对应的类实例中:
inputData = {contact__name:"john",othercontact__name:"sue",othercontact2__name:"joe",company__id:"123"}
规则说明:
- 每个属性由「类名 + '__' + 属性名」组成
- 属性值均为字符串
- inputData属性数量不超过100个
当前我采用的实现方式如下,但不确定是否为最优或最高效方案:
const contact = new Contact(), othercontact = new Contact(), company = new Company(), custom = new Custom(); const sortInputIntoObjects = (_inputData) => { let subkey = []; const tempObj = {}; for (key in _inputData) { subkey = key.split('__'); switch (subkey[0]) { case 'contact': { contact[subkey[1]] = _inputData[key]; break; } case 'othercontact': { othercontact[subkey[1]] = _inputData[key]; break; } case 'company': { company[subkey[1]] = _inputData[key]; break; } default: { custom[subkey[1]] = _inputData[key]; } } } };
拆分完成后,每个对象会被发送至对应的API。请问是否有更优实现方式?比如使用map/reduce/filter,还是当前方案已足够?
注:此代码用于Zapier,仅支持V8引擎的ES8语法,无法使用外部库。
解答
当前方案的可行性
首先明确:因为inputData的属性数量最多100个,你的现有方案完全够用,性能上没有任何问题——这种量级的循环操作,在JS里耗时可以忽略不计,没必要过度纠结"最优性能"。
更简洁易扩展的优化方案
如果要追求代码的可维护性(比如后续可能新增更多类实例),可以用实例映射表替代switch语句,代码更简洁且扩展性更强:
// 先定义类实例与类名的映射关系 const instanceMap = { contact: new Contact(), othercontact: new Contact(), company: new Company(), custom: new Custom() // 作为默认兜底实例 }; const sortInputIntoObjects = (_inputData) => { for (const key in _inputData) { // ES8解构赋值,直接拆分出类名和属性名 const [className, propName] = key.split('__'); // 找到对应实例,找不到则用custom const targetInstance = instanceMap[className] || instanceMap.custom; targetInstance[propName] = _inputData[key]; } };
这个方案的优势:
- 新增类实例时,只需要在
instanceMap里添加键值对,不用修改循环逻辑,符合"开放封闭原则" - 用解构赋值替代数组索引取值,代码可读性更高
- 性能和原方案持平,同样是单次循环遍历
关于map/reduce/filter的使用
这类数组方法确实可以实现需求,但并不适合当前场景:
- map/filter主要用于数组的转换、筛选,这里处理的是对象属性,用起来会很别扭
- reduce可以实现,但更适合生成新对象的场景,而我们是直接给已有实例赋值,强行用reduce会让代码可读性下降,比如:
const instances = { contact: new Contact(), othercontact: new Contact(), company: new Company(), custom: new Custom() }; Object.entries(inputData).reduce((acc, [key, value]) => { const [className, propName] = key.split('__'); const target = acc[className] || acc.custom; target[propName] = value; return acc; }, instances);
这段代码能实现功能,但比for循环的写法更绕,没必要为了用而用。
总结
- 如果只是满足当前需求,你的原方案完全没问题,无需改动
- 如果要考虑后续扩展,推荐用实例映射表的方案,代码更易维护
- map/reduce这类方法在这里属于"过度设计",不会带来性能或可读性的提升,不建议使用
内容的提问来源于stack exchange,提问作者John Hamman
相关产品推荐
相关产品推荐

