如何从嵌套对象中移除指定键值对且不修改原对象?
如何在不修改原对象的情况下移除嵌套对象中的指定键值对?
问题背景
你有一个包含多个嵌套对象的原对象:
const myObject = { myNestedObject1: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject2: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject3: { key1: "key1", key2: "key2", key3: "key3" } };
希望生成一个结构相同,但每个嵌套对象都移除key2: "key2"的新对象,且绝对不能修改原对象,期望结果如下:
const desiredObject = { myNestedObject1: { key1: "key1", key3: "key3" }, myNestedObject2: { key1: "key1", key3: "key3" }, myNestedObject3: { key1: "key1", key3: "key3" } };
你当前代码的问题
你用_.transform结合Object.assign({}, myObject)的思路没问题,但Object.assign是浅拷贝——它只会复制原对象的顶层属性,嵌套对象还是和原对象共享引用。所以当你执行delete value["key2"]时,实际上修改的是原对象里的嵌套对象,这就导致了原对象被改动。
解决方案
1. 原生JavaScript实现(无需依赖库)
利用Object.fromEntries和Object.entries的组合,遍历每个嵌套对象并生成排除key2的新对象,全程都是纯操作,不会影响原对象:
const myObject = { myNestedObject1: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject2: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject3: { key1: "key1", key2: "key2", key3: "key3" } }; const newObject = Object.fromEntries( Object.entries(myObject).map(([parentKey, nestedObj]) => { // 对每个嵌套对象过滤掉key2,生成新对象 const filteredNested = Object.fromEntries( Object.entries(nestedObj).filter(([key]) => key !== "key2") ); return [parentKey, filteredNested]; }) ); // 验证结果 console.log(newObject); // 符合期望的结构 console.log(myObject.myNestedObject1.key2); // 原对象的key2依然存在,未被修改
2. Lodash实现(简洁高效)
用Lodash的_.mapValues和_.omit组合是最简洁的方式,这两个方法都是纯函数,返回新对象而不修改原数据:
const myObject = { myNestedObject1: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject2: { key1: "key1", key2: "key2", key3: "key3" }, myNestedObject3: { key1: "key1", key2: "key2", key3: "key3" } }; // _.mapValues遍历原对象的每个值,_.omit移除指定键并返回新对象 const newObject = _.mapValues(myObject, (nestedObj) => _.omit(nestedObj, "key2")); // 验证结果 console.log(newObject); // 目标结构 console.log(myObject.myNestedObject1.key2); // 原对象未被修改
这个方案的优势在于代码非常简洁,Lodash已经帮我们处理了深拷贝和过滤的细节,完全不用担心副作用。
内容的提问来源于stack exchange,提问作者Emille C.
相关产品推荐
相关产品推荐

