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)。
评论区