标签JavaScript | 前端开发 | 数组操作 | 实战技巧 前言在日常开发中我们经常需要从数组中提取指定范围的值。比如获取最近7天的数据、提取表格中D列到F列的内容、截取数组中间一段做分析等等。看似简单的需求其实有N 种实现方式今天就来总结一下 JS 中获取数组指定范围值的所有方法从最老的语法到最新的 ES2023 特性一网打尽 方法一览序号方法是否修改原数组兼容性推荐度代码量1slice(start, end)⭐❌ 不修改✅ IE9⭐⭐⭐⭐⭐1行2splice(start, count)✅ 修改✅ IE4⭐⭐⭐1行3forif手动截取❌ 不修改✅ IE6⭐⭐⭐⭐5行4filter() 索引❌ 不修改✅ ES5⭐⭐⭐1行5reduce()累积❌ 不修改✅ ES5⭐⭐2行6at() 循环ES2022❌ 不修改✅ ES2022⭐⭐⭐⭐1行 方法详解✅ 方法1slice(start, end)⭐⭐⭐⭐⭐ 最推荐这是最常用、最简洁的方法左闭右开不会修改原数组constlist[10,20,30,40,50,60,70];// ✅ 提取索引 2 到 5不包含5constsub1list.slice(2,5);console.log(sub1);// [30, 40, 50]// ✅ 提取索引 3 到末尾constsub2list.slice(3);console.log(sub2);// [40, 50, 60, 70]// ✅ 使用负数索引从末尾开始constsub3list.slice(-4,-1);console.log(sub3);// [40, 50, 60]// ✅ 提取最后一个元素等同于 at(-1)constsub4list.slice(-1);console.log(sub4[0]);// 70关键规则规则说明示例slice(start, end)左闭右开包含 start不包含 endslice(2,5)→ 索引 2,3,4slice(start)从 start 到末尾slice(3)→ 索引 3,4,5…slice(-3)倒数第3个到末尾slice(-3)→ 最后3个slice(-4,-1)倒数第4个到倒数第1个不含→ 倒数第4,3,2个start end返回空数组slice(5,2)→[]底层原理slice()是浅拷贝对于嵌套数组/对象内部引用仍指向原数据。⚠️ 方法2splice(start, count)⭐⭐⭐ 会修改原数组splice()会删除并返回指定范围的元素原数组会被修改constlist[10,20,30,40,50];// ✅ 从索引1开始删除3个元素constremovedlist.splice(1,3);console.log(removed);// [20, 30, 40]console.log(list);// [10, 50] ⚠️ 原数组被改了适用场景需要同时删除并获取元素时使用。方法用途是否修改原数组slice(start, end)提取范围只读❌ 不修改splice(start, count)删除范围可写✅ 修改✅ 方法3forif手动截取 ⭐⭐⭐⭐ 兼容老浏览器如果需要复杂条件判断比如排除空行用手动循环最灵活constlist[10,20,30,40,50,60,70];constresult[];// ✅ 提取索引 2 到 5 的元素for(leti2;i5;i){result.push(list[i]);}console.log(result);// [30, 40, 50]// ✅ 提取索引 3 到末尾for(leti3;ilist.length;i){result.push(list[i]);}console.log(result);// [40, 50, 60, 70]实战案例排除空行数据JS宏场景// 读取表格数据排除空行functiongetTableData(sheetData){letresults[];// 从第1行开始跳过表头for(leti1;isheetData.length;i){letrowDatasheetData[i].slice(0,3);// 提取前3列// 正则判断是否全是空白字符if(!/^[\s]*$/.test(rowData.join())){results.push(rowData);}}returnresults.length0?results:;} 正则/^[\s]*$/解析^开头[\s]*零个或多个空白字符$结尾 → 整行都是空白✅ 方法4filter() 索引判断 ⭐⭐⭐ 函数式风格constlist[10,20,30,40,50,60,70];// ✅ 提取索引 2 到 5 的元素constsublist.filter((_,index)index2index5);console.log(sub);// [30, 40, 50]// ✅ 提取倒数3个元素constlast3list.filter((_,index)indexlist.length-3);console.log(last3);// [50, 60, 70]优点代码简洁函数式风格缺点性能略差需要遍历整个数组⭐ 方法5reduce()累积 ⭐⭐ 函数式编程constlist[10,20,30,40,50,60,70];// ✅ 提取索引 2 到 5 的元素constsublist.reduce((acc,cur,i){if(i2i5)acc.push(cur);returnacc;},[]);console.log(sub);// [30, 40, 50]优点函数式编程适合链式调用缺点代码复杂性能一般 方法6at() 循环ES2022⭐⭐⭐⭐ 语义最清晰ES2022 新增的at()支持负数索引语义最清晰constlist[10,20,30,40,50,60,70];// ✅ 提取最后3个元素constlast3[list.at(-3),list.at(-2),list.at(-1)];console.log(last3);// [50, 60, 70]// ✅ 通用函数提取任意范围functiongetRange(arr,start,end){constresult[];for(letistart;iend;i){result.push(arr.at(i));}returnresult;}console.log(getRange(list,2,5));// [30, 40, 50]方法正序索引逆序索引示例arr[i]✅arr[0]❌ 不支持arr[0]→ 10arr.at(i)✅arr.at(0)✅arr.at(-1)arr.at(-1)→ 70 性能对比100万次循环方法耗时性能排名推荐度slice(start, end)~15ms 第1名⭐⭐⭐⭐⭐forpush~18ms 第2名⭐⭐⭐⭐at() 循环~20ms 第3名⭐⭐⭐⭐filter()~80ms第4名⭐⭐⭐reduce()~120ms第5名⭐⭐splice()~25ms第6名但会修改⭐⭐⭐结论slice()性能最好for循环紧随其后函数式方法稍慢但代码优雅️ 安全写法防止越界constlist[10,20,30];// ❌ 不安全end 超出范围会返回到末尾但 start 超出会返回空数组constsub1list.slice(5,10);// []// ✅ 安全写法限制范围functionsafeSlice(arr,start,end){startMath.max(0,start);endMath.min(arr.length,end);returnarr.slice(start,end);}console.log(safeSlice(list,1,10));// [20, 30] 实战场景场景1获取最近7天数据constprices[10.5,20.3,15.8,12.1,18.9,22.5,19.8,25.3,28.7,30.2];// ✅ 提取最近7天constlast7prices.slice(-7);console.log(last7);// [18.9, 22.5, 19.8, 25.3, 28.7, 30.2]场景2提取表格指定列JS宏// 提取 D列 到 F列索引3到6左闭右开constfangwei[3,6];constcolDatasheetData[i].slice(fangwei[0],fangwei[1]);// D列索引3, F列索引5, slice(3,6) → 索引3,4,5 → D,E,F列场景3排除空行后提取范围constrawData[[10,20,30],[],// 空行[40,50,60],null,// 空行[70,80,90]];constfilteredrawData.filter(rowrowrow.length0);constresultfiltered.slice(1,3);// 提取第2到第3行console.log(result);// [[40, 50, 60]] 封装通用函数/** * 获取数组指定范围的值 * param {Array} arr - 原数组 * param {Number} start - 起始索引支持负数 * param {Number} end - 结束索引不包含支持负数可省略 * returns {Array} 范围内的值 */functiongetRange(arr,start,end){if(endundefined){returnarr.slice(start);// 从 start 到末尾}returnarr.slice(start,end);}// 使用示例constlist[10,20,30,40,50,60,70];console.log(getRange(list,2,5));// [30, 40, 50]console.log(getRange(list,-3));// [50, 60, 70]console.log(getRange(list,-4,-1));// [40, 50, 60] 最终推荐场景推荐方法代码✅通用场景首选slice(start, end)arr.slice(2, 5)✅现代项目ES2022at() 循环arr.at(i)✅兼容老浏览器forpush手动循环✅需要删除原数据splice(start, count)arr.splice(2, 3)✅函数式风格filter()arr.filter((_,i)i2i5)❌不推荐reverse()[0]等会修改原数组 总结表格6种方法序号方法修改原数组兼容性性能推荐指数1slice(start, end)❌IE9⭐⭐⭐⭐⭐2splice(start, count)✅IE4⭐⭐⭐3forif❌IE6⭐⭐⭐⭐4filter()❌ES5第4名⭐⭐⭐5reduce()❌ES5第5名⭐⭐6at() 循环❌ES2022⭐⭐⭐⭐ 一句话总结万能首选slice(start, end)—— 不修改原数组、性能最优、兼容性好语义最清晰at(index)—— 正负索引都支持一看就懂️最灵活forif—— 复杂条件判断的不二之选觉得有用的话点个赞 收藏 ⭐ 吧有问题欢迎评论区讨论参考文档MDN - Array.prototype.slice()MDN - Array.prototype.at()MDN - Array.prototype.splice()