带数字键与浮点值的JavaScript对象在iOS上归约行为异常咨询
问题:Lodash _.reduce 在iOS设备上处理对象时出现不可预测行为
先把你的场景和代码再明确一下:
我们有两个配置对象:
const ReductionMap = { '10': 10.5, '1000': 20.5 } const initialValues = { '10': 110, '1000': 120 }
使用Lodash v4.17.5的_.reduce来生成每个值减去对应ReductionMap值的新对象:
const reducedValues = _.reduce( initialValues, (acc, value, key) => ({ ...acc, [key]: value - ReductionMap[key] }), {} )
预期结果是:
{ '10': 99.5, '1000': 99.5 }
但在iOS移动设备上出现了不可预测的行为。
问题原因分析
你当前的写法每次迭代都会通过对象展开运算符{...acc, ...}创建一个全新的累加对象,这种频繁的对象创建和展开操作,在部分旧版本的iOS Safari JS引擎中,可能会触发一些意外的行为(比如键的遍历顺序异常、内存回收导致的计算中断,或者引擎对展开运算符的实现bug)。虽然ES2015+规范了对象键的遍历顺序,但旧iOS浏览器可能没有完全遵循,叠加频繁对象创建的话,就会出现不可预测的结果。
解决方案
推荐两种更稳定的写法,都能解决iOS上的兼容性问题:
方案1:直接修改累加器对象(更高效)
不要每次迭代都创建新对象,直接在累加器上赋值,这也是Lodash _.reduce的常规用法:
const reducedValues = _.reduce(initialValues, (acc, value, key) => { acc[key] = value - ReductionMap[key]; return acc; }, {});
这种写法避免了频繁的对象复制,性能更优,同时在旧JS引擎中表现更稳定。
方案2:使用_.mapValues(语义更清晰)
既然你的需求是遍历对象的每个值并转换,用Lodash专门提供的_.mapValues会更合适,它的内部实现已经做了兼容性处理:
const reducedValues = _.mapValues(initialValues, (value, key) => value - ReductionMap[key]);
这个方法语义明确,代码更简洁,也能避免手动处理累加器可能带来的问题。
这两种写法都能稳定得到你预期的结果,且在iOS设备上的兼容性更好。
内容的提问来源于stack exchange,提问作者Alexander Wallin
相关产品推荐
相关产品推荐

