前言 数组是前端开发中最常用的数据结构,JS 提供了 30+ 个数组方法。本文按功能分类整理,每个方法配实战场景,帮你告别”只会 forEach”的尴尬。
一、增删改查 push / pop — 尾部操作 1 2 3 4 const arr = [1 , 2 , 3 ]arr.push (4 , 5 ) arr.pop ()
push 修改原数组,返回新长度;pop 修改原数组,返回被删元素。
unshift / shift — 头部操作 1 2 3 4 const arr = [2 , 3 , 4 ]arr.unshift (1 ) arr.shift ()
头部操作比尾部慢,因为需要移动所有元素。大数据量优先用 push/pop。
splice — 万能增删改 1 2 3 4 5 6 7 8 9 10 const arr = [1 , 2 , 3 , 4 , 5 ]arr.splice (2 , 2 ) arr.splice (1 , 0 , 'a' , 'b' ) arr.splice (1 , 2 , 'x' )
slice — 切片(不修改原数组) 1 2 3 4 5 6 7 8 const arr = [1 , 2 , 3 , 4 , 5 ]arr.slice (1 , 3 ) arr.slice (2 ) arr.slice (-2 ) const copy = arr.slice ()
slice 不修改原数组,常用于分页截取和浅拷贝。
二、遍历方法(不修改原数组) forEach — 纯遍历 1 2 3 4 5 6 7 8 9 const arr = [1 , 2 , 3 ]arr.forEach ((item, index, array ) => { console .log (item, index) })
map — 映射转换(高频) 1 2 3 4 5 6 7 8 9 10 11 const users = [{ id : 1 , name : '张三' }, { id : 2 , name : '李四' }]const ids = users.map (u => u.id ) const options = users.map (u => ({ value : u.id , label : u.name }))
filter — 过滤筛选(高频) 1 2 3 4 5 6 7 8 9 10 11 const list = [1 , 2 , 3 , 4 , 5 , 6 ]const evens = list.filter (n => n % 2 === 0 ) const users = [{ name : 'a' , active : true }, { name : 'b' , active : false }]const activeUsers = users.filter (u => u.active ) const unique = list.filter ((v, i, arr ) => arr.indexOf (v) === i)
find / findIndex — 查找(高频) 1 2 3 4 5 6 7 const users = [{ id : 1 , name : '张三' }, { id : 2 , name : '李四' }]const user = users.find (u => u.id === 2 ) const index = users.findIndex (u => u.name === '张三' )
some / every — 条件判断 1 2 3 4 5 6 7 8 9 10 11 const scores = [85 , 90 , 78 , 92 ]scores.some (s => s >= 60 ) scores.every (s => s >= 60 ) const fields = ['张三' , '13800138000' , '' ]const allFilled = fields.every (Boolean )
三、归并方法 reduce — 万能聚合(核心) 1 arr.reduce ((prev, cur, index, arr ) => { }, initialValue)
场景一:数组求和
1 const sum = [1 , 2 , 3 , 4 ].reduce ((p, c ) => p + c, 0 )
场景二:数组对象分组
1 2 3 4 5 6 7 8 9 10 11 const list = [ { type : '水果' , name : '苹果' }, { type : '蔬菜' , name : '白菜' }, { type : '水果' , name : '香蕉' } ] const grouped = list.reduce ((acc, item ) => { (acc[item.type ] ||= []).push (item) return acc }, {})
场景三:数组去重
1 2 3 4 5 6 const arr = [1 , 2 , 3 , 2 , 1 , 4 ]const unique = arr.reduce ((acc, v ) => { if (!acc.includes (v)) acc.push (v) return acc }, [])
场景四:统计出现次数
1 2 3 4 5 6 const names = ['Alice' , 'Bob' , 'Alice' , 'Tom' , 'Bob' ]const count = names.reduce ((acc, name ) => { acc[name] = (acc[name] || 0 ) + 1 return acc }, {})
场景五:扁平化嵌套数组
1 2 3 4 5 6 7 function flatten (arr ) { return arr.reduce ((acc, item ) => { return acc.concat (Array .isArray (item) ? flatten (item) : item) }, []) } flatten ([1 , [2 , [3 , 4 ]]])
四、排序与反转 sort — 排序(修改原数组) 1 2 3 4 5 6 7 8 9 10 11 12 const nums = [3 , 1 , 10 , 5 ]nums.sort ((a, b ) => a - b) nums.sort ((a, b ) => b - a) const list = [{ age : 25 }, { age : 18 }, { age : 30 }]list.sort ((a, b ) => a.age - b.age ) const names = ['张三' , '李四' , '王五' ]names.sort ((a, b ) => a.localeCompare (b))
reverse — 反转(修改原数组) 1 2 3 4 5 const arr = [1 , 2 , 3 ]arr.reverse () const reversed = [...arr].reverse ()
五、连接与填充 concat — 合并数组 1 2 3 4 5 const a = [1 , 2 ]const b = [3 , 4 ]const c = a.concat (b) const d = [...a, ...b]
join — 转字符串 1 2 3 4 const arr = ['a' , 'b' , 'c' ]arr.join () arr.join ('-' ) arr.join ('' )
fill — 填充 1 2 const arr = new Array (5 ).fill (0 ) ;[1 , 2 , 3 , 4 ].fill ('x' , 1 , 3 )
flat / flatMap — 扁平化 1 2 3 4 5 6 7 8 9 const arr = [1 , [2 , [3 , [4 ]]]]arr.flat () arr.flat (2 ) arr.flat (Infinity ) const result = [1 , 2 , 3 ].flatMap (n => [n, n * 2 ])
六、实战应用场景 1. 树形数据查找节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function findNode (tree, id ) { for (const node of tree) { if (node.id === id) return node if (node.children ) { const found = findNode (node.children , id) if (found) return found } } return null } const tree = [ { id : 1 , name : 'root' , children : [{ id : 2 , name : 'child' }] } ] console .log (findNode (tree, 2 ))
2. 数组转树结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function listToTree (list, parentId = null ) { return list .filter (item => item.pid === parentId) .map (item => ({ ...item, children : listToTree (list, item.id ) })) } const list = [ { id : 1 , pid : null , name : 'root' }, { id : 2 , pid : 1 , name : 'child' }, { id : 3 , pid : 2 , name : 'grandchild' } ] const tree = listToTree (list)
3. 数据分页 1 2 3 4 5 6 7 function paginate (arr, page, size ) { const start = (page - 1 ) * size return arr.slice (start, start + size) } const data = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]paginate (data, 2 , 3 )
4. 数组对象去重 1 2 3 4 5 6 7 8 9 10 11 function uniqueBy (arr, key ) { const seen = new Map () return arr.filter (item => !seen.has (item[key]) && seen.set (item[key], 1 )) } const list = [ { id : 1 , name : 'a' }, { id : 2 , name : 'b' }, { id : 1 , name : 'c' } ] uniqueBy (list, 'id' )
5. 交集 / 并集 / 差集 1 2 3 4 5 6 7 8 9 10 11 const a = [1 , 2 , 3 , 4 ]const b = [3 , 4 , 5 , 6 ]const intersection = a.filter (v => b.includes (v)) const union = [...new Set ([...a, ...b])] const diff = a.filter (v => !b.includes (v))
七、Vue3 中数组方法的应用 1. computed 中的数据处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <script setup> import { ref, computed } from 'vue' const todos = ref([ { id: 1, text: '学 Vue', done: true }, { id: 2, text: '写项目', done: false }, { id: 3, text: '复习', done: false } ]) // 用 filter + map 派生新数据 const undoneTodos = computed(() => todos.value .filter(t => !t.done) .map(t => ({ ...t, date: new Date() })) ) // 用 reduce 统计 const stats = computed(() => todos.value.reduce((acc, t) => { t.done ? acc.done++ : acc.undone++ return acc }, { done: 0, undone: 0 }) ) </script>
2. 级联选择器数据处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <script setup> import { ref, computed } from 'vue' const regions = ref([ { id: '1', pid: null, name: '广东省' }, { id: '2', pid: '1', name: '深圳市' }, { id: '3', pid: '2', name: '南山区' } ]) // filter + map 构建级联数据 const options = computed(() => { // 先转成树 const provinces = regions.value .filter(r => !r.pid) .map(p => ({ value: p.id, label: p.name, children: regions.value .filter(r => r.pid === p.id) .map(c => ({ value: c.id, label: c.name, children: regions.value .filter(r => r.pid === c.id) .map(d => ({ value: d.id, label: d.name })) })) })) return provinces }) </script>
3. 表格排序与搜索 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <script setup> import { ref, computed } from 'vue' const users = ref([ { name: '张三', age: 25, active: true }, { name: '李四', age: 30, active: false }, { name: '王五', age: 20, active: true } ]) const keyword = ref('') const sortBy = ref('age') // 搜索 + 排序组合 const filteredUsers = computed(() => { return users.value .filter(u => u.name.includes(keyword.value)) // 过滤 .sort((a, b) => a[sortBy.value] > b[sortBy.value] ? 1 : -1) // 排序 }) const activeCount = computed(() => users.value.filter(u => u.active).length ) </script>
4. 拖拽排序 1 2 3 4 5 6 7 8 function handleDragEnd (arr, fromIndex, toIndex ) { const item = arr.splice (fromIndex, 1 )[0 ] arr.splice (toIndex, 0 , item) } const list = ref ([1 , 2 , 3 , 4 , 5 ])handleDragEnd (list.value , 0 , 3 )
八、性能速查
场景
推荐方法
原因
遍历执行副作用
for...of / forEach
直接,不需返回值
映射新数组
map
语义清晰,链式调用
筛选条件
filter
返回新数组,不修改原数组
找第一个匹配
find / findIndex
找到即停,比 filter 高效
聚合/统计
reduce
一次遍历完成多种计算
有任一满足
some
找到即停
全部满足
every
遇到 false 即停
大量数据头部操作
避免 unshift/shift
元素位移开销大
总结
分类
方法
增删改
push pop unshift shift splice slice
遍历
forEach map filter find findIndex some every
归并
reduce reduceRight
排序
sort reverse
连接
concat join flat flatMap
其他
fill includes indexOf lastIndexOf Array.from Array.of
记住每个方法的返回值 和是否修改原数组 ,是选对方法的关键
reduce 是万能工具,分组、去重、扁平化都能做
Vue3 中 computed + 数组方法 = 声明式数据处理的黄金搭档
内容由 AI 生成,仅供参考。本文发布于 码上学习 ,转载请注明出处。