JS 数组系列专题文章目录
入门篇
第 1 篇:认识 JavaScript 数组——从入门到操作基础
👉 介绍数组的概念、创建方式、索引与长度的使用,以及最基础的遍历方法。适合刚接触数组的新手。第 2 篇:数组的增删改全解析(push、pop、splice)
👉 系统讲解数组的增删改方法,包括push
、pop
、shift
、unshift
、splice
、fill
,并结合小案例说明。常用方法篇
第 3 篇:数组的查找与判断方法大全
👉 详细介绍如何在数组中查找元素,包括indexOf
、lastIndexOf
、includes
、find
、findIndex
、some
、every
等。第 4 篇:数组的排序与合并技巧(sort、concat、slice)
👉 讲解数组排序与反转的方法,以及合并、切片、字符串化的常见操作,重点讲解sort
排序中的注意点。进阶篇
第 5 篇:数组的迭代与转换(map、filter、reduce 全解)
👉 深入剖析高阶方法map
、filter
、reduce
,包括实际应用场景:数组求和、数据统计、扁平化处理等。第 6 篇:数组的实用技巧与案例集锦
👉 介绍常见的数组处理技巧:去重(多种写法对比)、扁平化(flat
与递归实现)、字符串与数组互转、对象数组排序。高阶篇
第 7 篇:类数组与稀疏数组——容易忽略的细节
👉 解释什么是类数组(arguments
、NodeList
),如何转换为真数组,稀疏数组的特性和坑点。第 8 篇:不可变数组操作与函数式编程思路
👉 如何在不修改原数组的前提下进行操作(扩展运算符、concat
、map
等),结合函数式编程的思想讲解。实战 & 面试篇
第 9 篇:手写数组常用方法(map、filter、reduce)
👉 从源码角度模拟实现常见数组方法,帮助加深理解,提升面试竞争力。第 10 篇:数组实战应用与高频面试题精选
👉 总结数组在实战中的应用:两数之和、数组旋转、最大最小值查找、groupBy
、分页实现,涵盖面试常考题。
常用方法与何时用它们(先上速查表)
includes(value)
—— 询问“有没有这个值?”,返回true/false
(适合原始类型快速查存在性)。indexOf(value)
/lastIndexOf(value)
—— 找到值在数组中首次/最后一次出现的下标,找不到返回-1
(对原始类型或引用完全相等的对象有效)。indexOf
使用严格相等比较(===
),因此对NaN
找不到。find(predicate)
—— 返回第一个满足条件的元素(不是下标),找不到返回undefined
。predicate
是回调函数,可写复杂条件。findIndex(predicate)
—— 返回第一个满足条件元素的下标,找不到返回-1
。some(predicate)
—— 检查是否存在至少一个元素满足条件(相当于逻辑 ∃),返回布尔。every(predicate)
—— 检查所有元素是否都满足条件(相当于逻辑 ∀),空数组会返回true
(数学上称作“类真”/vacuously true)。另外,every
/some
/find
等回调只会被调用在数组中存在值的索引(稀疏数组的空位会跳过)。
(上面这些方法绝大多数都是线性扫描 —— 时间复杂度 O(n),n 很大时要注意性能)
详细讲解 + 代码示例(生活类比 + 实战)
1) includes
:问一句“有吗?”
类比:把包打开问朋友:“包里有没有零食?” 他给你 是/否
回答。
const arr = [1, 2, 3, NaN];
console.log(arr.includes(2)); // true
console.log(arr.includes(5)); // false
// includes 使用 SameValueZero 比较,因此能识别 NaN
console.log(arr.includes(NaN)); // true
- 适用场景:你只想知道有没有某个(通常是原始)值时用。它内部使用的是 SameValueZero(这也是为什么
NaN
会被判断为“相等”的原因)。
2) indexOf
/ lastIndexOf
:要位置就找下标
类比:你问“我的公交卡放在哪个抽屉里?”朋友指给你第几个抽屉编号(下标)。
const a = ['a', 'b', 'a', 'c'];
console.log(a.indexOf('a')); // 0 (第一个出现位置)
console.log(a.lastIndexOf('a')); // 2 (最后一个出现位置)
console.log(a.indexOf('x')); // -1 (没找到)
注意:
indexOf
使用严格相等(===
),所以NaN
永远找不到(返回 -1)。如果你需要判断存在性,考虑includes
。indexOf
会跳过稀疏数组的空位。
3) find
:找到“第一个符合条件的那个人”,返回元素本身
类比:你从人群里问“谁带了雨伞?”,那第一个举手的人就是你要的那位。
const users = [
{ id: 1, name: '小明', vip: false },
{ id: 2, name: '小红', vip: true },
{ id: 3, name: '小李', vip: true },
];
// 找到第一个 vip 用户
const firstVip = users.find(u => u.vip);
console.log(firstVip); // { id: 2, name: '小红', vip: true }
// 找不到时返回 undefined
console.log(users.find(u => u.id === 99)); // undefined
find
的回调接收三个参数:(element, index, array)
,并可带可选thisArg
。如果需要下标,改用findIndex
。
4) findIndex
:找下标(为 splice
/ 替换等场景准备)
const fruits = ['苹果', '香蕉', '梨', '香蕉'];
const idx = fruits.findIndex(f => f === '香蕉');
console.log(idx); // 1
if (idx !== -1) {
fruits.splice(idx, 1); // 删除第一个香蕉
}
findIndex
找不到时返回-1
。适合你需要知道元素位置以便后续修改/删除时使用。
5) some
vs every
:布尔量的“有/全”
类比:
some
:队里有没有能唱高音的人?(存在一个就够)every
:队里所有人都会唱歌吗?(每个人都要会)
const scores = [80, 90, 100];
console.log(scores.some(s => s < 60)); // false(有没有不及格的)
console.log(scores.every(s => s >= 60)); // true(是否都及格)
// 空数组例子
console.log([].some(x => x > 0)); // false(没元素,自然不存在满足的)
console.log([].every(x => x > 0)); // true(数学上的“全都满足”对空集成立)
every
对空数组返回true
,some
对空数组返回false
。这是数学逻辑的自然延伸(空集的“全真”)。另外,这些回调也会跳过稀疏数组的空位(不会被调用)。
6) find
vs filter
:找第一条还是找全部?
find
:返回第一个匹配项(或者undefined
)filter
:返回所有匹配项的新数组(可能是空数组[]
)
const arr = [1,2,3,4,5,6];
// 找第一个偶数
console.log(arr.find(x => x % 2 === 0)); // 2
// 找所有偶数
console.log(arr.filter(x => x % 2 === 0)); // [2,4,6]
选择规则:要单个直接 find
,要集合用 filter
。
7) 对象数组和引用类型的坑
const o1 = {name: 'A'};
const o2 = {name: 'A'};
const arr = [o1];
console.log(arr.indexOf(o1)); // 0 (同一个引用)
console.log(arr.indexOf(o2)); // -1 (内容一样,但引用不是同一个)
indexOf/includes/lastIndexOf
对于对象比较的是引用(同一个对象实例才相等)。如果想按对象属性查找,用find
:
const found = arr.find(x => x.name === 'A');
8) findLast
/ findLastIndex
(新朋友)
如果你想从右往左找(找到最后一个满足条件的元素/下标),标准里已经有 findLast
和 findLastIndex
可以用,不过它们在某些旧环境可能还不支持(要注意兼容性或 polyfill)。如果环境不支持,可以手动反转数组或倒序遍历。
9) 关于稀疏数组(空位)和回调方法
许多回调式方法(forEach
、map
、filter
、find
、some
、every
等)在遇到稀疏数组的“空位”时,会跳过不调用回调(也就是说回调只会被调用在那些已有值的索引上)。这点在处理稀疏数组时要留个心。
记住这几句口诀
- “有没?”用
includes
;要下标用indexOf
/findIndex
;要元素用find
。 indexOf
用===
(无法识别NaN
),includes
用 SameValueZero(可识别NaN
)。some
= 存在性(∃),every
= 全符合(∀,空数组返回true
)。
评论区