数组转对象后键顺序与原数组不符,问题原因排查
对象键顺序与原数组不一致的原因及解决办法
问题背景
原数组:
let arr = ['0 abc', '81 abc', '63 abc', '108 abc', '100 abc', '80 abc', '54 abc', '128 abc', '32 abc', '9 abc'];
期望得到按原数组顺序排列键的对象:
{ '0': '0 abc', '81': '81 abc', '63': '63 abc', '108': '108 abc', ... }
编写的转换函数:
function arrayObj(arr){ let obj = arr.reduce((prevVal, item) => { let sp = item.split(' '); let number = sp.splice(0,1); prevVal[number] = item; return prevVal; }, {}); return obj; }
实际输出的对象键被自动排序:
{ '0': '0 abc', '9': '9 abc', '32': '32 abc', '54': '54 abc', '63': '63 abc', '80': '80 abc', '81': '81 abc', '100': '100 abc', '108': '108 abc', '128': '128 abc' }
原因分析
这不是你的代码逻辑错误,而是JavaScript普通对象的数字类型键(包括可被解析为十进制整数的字符串键)会被引擎自动按升序排序。这类键会被当作类数组的索引处理,优先级高于普通字符串键,插入顺序不被保留。
解决办法
1. 使用Map保存(推荐,严格保留插入顺序)
Map是ES6新增的数据结构,会严格按照键的插入顺序存储和遍历:
function arrayToMap(arr){ return arr.reduce((prevVal, item) => { const [key] = item.split(' '); // 解构直接获取第一个元素,更简洁 prevVal.set(key, item); return prevVal; }, new Map()); }
使用示例:
const resultMap = arrayToMap(arr); console.log(resultMap.get('81')); // 输出 '81 abc' // 遍历会按原数组顺序 resultMap.forEach((value, key) => { console.log(key, value); });
2. 修改键的格式(如果必须使用普通对象)
给数字键添加非数字前缀,避免被引擎当作索引排序:
function arrayObj(arr){ return arr.reduce((prevVal, item) => { const [num] = item.split(' '); const key = `prefix_${num}`; // 添加前缀 prevVal[key] = item; return prevVal; }, {}); }
输出结果会保留原数组顺序:
{ 'prefix_0': '0 abc', 'prefix_81': '81 abc', 'prefix_63': '63 abc', ... }
额外优化点
你的原代码中let number = sp.splice(0,1);返回的是一个数组(splice方法返回被删除元素组成的数组),虽然JS会自动将数组转为字符串作为键,但直接用const [number] = item.split(' ');或者const number = item.split(' ')[0];更直观,也能避免不必要的数组修改操作。
内容的提问来源于stack exchange,提问作者eduardo
相关产品推荐
相关产品推荐

