JSON.stringify replacer函数异常:保留指定前缀属性失效问题
问题:为何用JSON.stringify的replacer保留特定前缀属性失败,移除却正常?
我想保留对象中所有属性名以特定字符串开头的属性,移除其他属性。但以下尝试仅保留foo属性的代码返回undefined,相反逻辑(移除foo)却能正常运行。
代码示例:
const o = { foo: 1, bar: 2, baz: 3 }; console.log(JSON.stringify(o, (k, v) => k.startsWith('f') ? v : undefined)); // undefined -> 为什么不是 {"foo":1} ? console.log(JSON.stringify(o, (k, v) => !k.startsWith('f') ? undefined : v)); // undefined -> 为什么不是 {"foo":1} ? console.log(JSON.stringify(o, (k, v) => !k.startsWith('f') ? v : undefined)); // {"bar":2,"baz":3} Object.keys(o).forEach(key => { console.log(key, key.startsWith('f')); }); // foo,true // bar,false // baz,false
原因分析
问题出在JSON.stringify的replacer函数的初始调用规则上:
- 第一次调用replacer时,参数
k是空字符串"",对应的v是整个目标对象o。 - 当你写
k.startsWith('f') ? v : undefined时,空字符串不满足前缀条件,直接返回undefined,这会让JSON.stringify直接丢弃整个对象,最终输出undefined。 - 而相反逻辑
!k.startsWith('f') ? v : undefined时,空字符串满足条件,返回整个对象,之后replacer才会遍历对象的每个属性,此时排除foo、保留其他属性,所以能正常输出结果。
解决方法
方法1:处理replacer的初始调用
在replacer里先判断初始调用的空字符串情况,返回整个对象后再过滤属性:
console.log(JSON.stringify(o, (k, v) => { if (k === "") return v; // 处理初始调用,返回整个对象 return k.startsWith('f') ? v : undefined; // 过滤属性 })); // 输出 {"foo":1}
方法2:提前过滤对象再序列化
直接先把对象过滤好,再进行JSON序列化,逻辑更直观:
const filteredObj = Object.fromEntries( Object.entries(o).filter(([key]) => key.startsWith('f')) ); console.log(JSON.stringify(filteredObj)); // 输出 {"foo":1}
内容的提问来源于stack exchange,提问作者droptix
相关产品推荐
相关产品推荐

