Array.from、Array.of、includes、find 和 findIndex 分别解决什么问题?
简化版
Array.from 把类数组或可迭代对象转成数组,Array.of 用参数创建数组;includes 判断是否包含某个值,能正确处理 NaN;find 返回第一个满足条件的元素,findIndex 返回它的索引。
这些方法让数组创建、转换和查找更明确,减少 Array.prototype.slice.call、indexOf 判断等旧写法的歧义。
详细版
Array.from("abc"); // ["a", "b", "c"]
Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]
Array.of(3); // [3]
new Array(3); // [empty × 3]
查找:
[1, NaN].includes(NaN); // true
[1, NaN].indexOf(NaN); // -1
const list = [{ id: 1 }, { id: 2 }];
list.find(item => item.id === 2); // { id: 2 }
list.findIndex(item => item.id === 2); // 1
它们的重点不是性能更强,而是语义更准确。
完整版教学
一、数组新增 API 的共同目标
ES6+ 给数组补了很多小 API,解决的是老写法不直观、边界容易误解的问题。
create: Array.of
convert: Array.from
contain: includes
search: find / findIndex
这类题别孤立背 API,要讲它们替代了哪些老写法、减少了哪些歧义。
二、Array.from 用于转换
Array.from 可以接收类数组对象,也可以接收可迭代对象。
const chars = Array.from("hello");
const nums = Array.from({ length: 5 }, (_, i) => i + 1);
第二个参数是映射函数,能避免先创建数组再 map。
Array.from({ length: 3 }, (_, i) => i * 2); // [0, 2, 4]
三、Array.of 解决构造器歧义
new Array(3) 表示创建长度为 3 的空位数组。
Array.of(3) 表示创建包含单个元素 3 的数组。
| 写法 | 结果 |
|---|---|
new Array(3) | [empty × 3] |
new Array(1, 2, 3) | [1, 2, 3] |
Array.of(3) | [3] |
Array.of 的语义更稳定:参数就是元素。
四、includes 比 indexOf 更适合包含判断
includes 返回布尔值,表达“是否包含”。
const roles = ["admin", "editor"];
roles.includes("admin"); // true
它还使用 SameValueZero 比较,能匹配 NaN。
[NaN].includes(NaN); // true
[NaN].indexOf(NaN); // -1
五、find 和 findIndex 的区别
find 返回元素,找不到返回 undefined。
findIndex 返回索引,找不到返回 -1。
const users = [{ id: 1 }, { id: 2 }];
const user = users.find(item => item.id === 2);
const index = users.findIndex(item => item.id === 2);
如果数组元素本身可能是 undefined,用 find 判断是否找到要更谨慎。
六、和稀疏数组的关系
Array.from({ length: 3 }) 会创建真实元素位,每个位置都会经过映射函数。
Array.from({ length: 3 }, () => 1); // [1, 1, 1]
new Array(3).map(() => 1); // [empty × 3]
这就是初始化固定长度数组时常用 Array.from 的原因。
七、常见误区与追问
- 误区:Array.from 只能转换类数组。 它也能转换可迭代对象,比如字符串、Set、Map。
- 误区:Array.of 和 new Array 没区别。 单个数字参数时结果完全不同。
- 误区:includes 和 indexOf 只是返回值不同。
includes能正确判断NaN。 - 误区:find 找不到时可以和 null 比较。 它返回
undefined,不是null。 - 追问:为什么初始化数组常用 Array.from? 它能避免空位数组导致
map不执行。 - 追问:findIndex 适合什么场景? 需要定位后删除、替换或插入附近元素时。
八、加强记忆
把它们放进四个动词:
from: convert
of: create
includes: contain
find/findIndex: search
回答时用 Array.of(3) 对比 new Array(3),再用 [NaN].includes(NaN) 对比 indexOf,两个例子足够把关键差异讲明白。