关于JSON.stringify中replacer函数返回值的疑问:为何直接数值运算失效而添加类型判断后正常?
为什么JSON.stringify的replacer第一种写法失效,第二种可行?
这问题问得很到位!要搞明白两种写法的差异,得先吃透JSON.stringify里replacer函数的执行逻辑。咱们结合你的场景一步步分析:
你的目标是把薪资对象let salaries = { james:100000, john:200000, jane:300000 };里的每个数值乘以1.1,再转成JSON字符串。
第一种写法的问题所在
先看你第一次写的代码:
let payjson = JSON.stringify(salaries, function replacer(key, value){ return value*1.1; });
JSON.stringify调用replacer函数的流程是先处理顶层对象,再递归遍历每个属性:
- 第一步,replacer会被调用一次,参数是
key: ""(空字符串代表顶层),value: 整个salaries对象 - 这时候你执行
value*1.1,本质是把一个对象和数字相乘,结果是NaN - 当replacer返回
NaN这种非对象值时,JSON.stringify会直接序列化这个值,不会再继续遍历对象里的james、john等属性
最终自然得不到你想要的结果,反而会输出"NaN"或者因为变量名错误(比如你写的pays而非salaries)出现其他异常。
第二种写法为什么能正常工作
再看你第二次的代码:
let payjson = JSON.stringify(salaries, function replacer(key, value){ return Number.isInteger(value)? Math.floor(value*1.1): value; });
这里的关键是加了判断逻辑,区分了顶层对象和属性数值:
- 第一次调用replacer处理顶层对象时,
Number.isInteger(value)会返回false(因为value是对象,不是整数),所以直接返回原对象 - 这时候
JSON.stringify会继续递归遍历对象的每个属性,当处理到james:100000这类键值对时,value是整数,Number.isInteger(value)返回true,就会执行value*1.1并取整,得到正确的薪资数值 - 每个属性都被正确处理后,最终就能生成你期望的JSON字符串:
{"james":110000,"john":220000,"jane":330000}
总结一下
replacer函数的执行顺序很重要,必须先允许顶层对象正常通过,才能让后续的属性遍历和处理生效。第一种写法忽略了顶层对象的处理,直接对所有value做乘法,导致序列化流程中断;第二种写法通过判断只处理数值类型的属性值,让整个序列化流程正常走完。
内容的提问来源于stack exchange,提问作者ekjkkk153
相关产品推荐
相关产品推荐

