探索数组 API 的妙用!转换、交互、迭代、杂项,数组时间到!

2025-06-08

发现 Array API 的好东西!

转型

相互作用

迭代

各种各样的

阵列时间!

这篇文章取自我的博客,所以一定要查看它以获取更多最新内容😉

毫无疑问,数组是最实用且极其流行的 JS 数据结构之一。这些索引集合一次又一次地证明了它们仍然是各种用例的最佳(甚至是唯一)选择。但是,如果没有其完整且极具表现力的API,数组本身也不会如此有价值。这就是今天文章的主题!😀

我们将介绍一些鲜为人知、甚至可能难以记住的数组 API原生方法。其中一些方法的起源令人惊讶地久远!借助它们,你将能够编写更简洁、更函数式(甚至具有函数式编程风格)且有时性能更佳的 JS 代码!有些方法可能更容易,有些则更难,但本文绝对不是针对完全的初学者!当然,如果你已经了解并记住了所有这些方法,不妨至​​少花点时间回顾一下细节或学习一些新的技巧!✨

转型

为了获得更好的阅读体验,我将所有列出的方法分为4 个独立的组。每个组包含至少共享一个特殊属性的方法。第一组称为“转换”。所有将数组转换为其他形式的方法都在这里。它们都以不可变的方式工作,在结果中返回新数组,而不会影响基础数组。

。筛选()

数组过滤功能有多好用,我想不用多说。有了它,.filter()你就能做到!你只需要传递一个过滤函数,该函数根据当前元素的值索引源数组,输出布尔值,指示给定元素是否应该包含在结果数组中。📋

const arr = [1,2,3,4];
const evenArr = arr.filter(num => num % 2 === 0); // [2,4]

Enter fullscreen mode Exit fullscreen mode

。地图()

.map()可能是FP定制 JS 编程中最受欢迎的数组方法之一。你可能已经知道,它会处理(“映射”)你的数组,并使用给定的映射函数返回包含新处理数据的新数组。该函数提供了一组标准参数,包括元素、其索引和源数组参数,并且应该返回应包含在结果中的值。所以,有了这些数据,你应该已经拥有了按你想要的方式更改数组所需的一切!😁

const arr = [1,2,3,4];
const oneMoreArr = arr.map(num => num + 1); // [2,3,4,5]
Enter fullscreen mode Exit fullscreen mode

.flat[Map]()

嵌套数组在当今非常常见。它们在表示二维或三维数据格式时尤其有用。这种维度完全可以进一步加深,但众所周知,之后跟踪和访问这些数据只会变得越来越困难。ECMAScript 规范的开发者们清楚地认识到了这种模式,并从最新的 ES 规范始终绿色的浏览器开始,.flat()为我们引入了新的方法。它的规则很简单——它只是按指定的深度(默认为 1)平嵌套数组,从而有效地使您的数组比以往更加扁平!

const arr = [1,[2,[3,[4]]]];
const flatten = arr.flat(3); // [1,2,3,4]

Enter fullscreen mode Exit fullscreen mode

还有另一种与数组展平相关的方法。我说的是.flatMap()and,正如你所料,它是.map()和的完美结合.flat()。基本上,你可以像 一样使用这个方法.map()——使用相同的参数集 和 等,但生成的数组稍后会被展平为1 层深度。很简单。那么,这种方法可能有哪些用例呢?为此,请考虑下面的字符串处理示例。

let arr = ["This is", "an", "example"];

const mappedArr = arr.map(x => x.split(" ")); 
// [["This","is"],"an","example"]

const flatMappedArr = arr.flatMap(x => x.split(" "));
// ["This","is","an","example"]
Enter fullscreen mode Exit fullscreen mode

可能有点粗略,但我想你明白了。一旦你理解了这个方法的工作原理,你肯定会找到一些自己的用例。顺便提一下,这种方法比单独使用性能更好⚡ 。.map().flat()

相互作用

“交互”类别将所有作用于源数组的方法分组,而不是提供全新的方法,而是改变它们或返回完全不同类型的值。🤯

。撤销()

这种方法确实简单,但鲜为人知,.reverse()正如其名——反转数组中元素的顺序。➰ 因此,最后一个元素应放在最前面。这在处理不同类型的队列时很可能会派上用场。请记住,此方法会改变源数组。

const arr = [1,2,3,4];
arr.reverse(); // [4,3,2,1]

Enter fullscreen mode Exit fullscreen mode

.reduce[Right]()

如果您想快速将数组转换(“reduce”)为单个值,可以使用该.reduce()方法轻松实现。只要提供正确的函数(即所谓的reducer),它稍后就会对数组的每个元素执行该函数,并将结果累积到一个变量中。

const arr = [1,2,3,4];
const sum = arr.reduce((sum, num) => sum + num); // 10

Enter fullscreen mode Exit fullscreen mode

参数函数应该返回累计值,该值稍后可以通过其第一个参数引用。在最佳情况下,该函数可以提供4 个参数(按给定顺序):

  • 累积值(可以是字符串、数组、对象或其他任何内容……);
  • 正在减少的数组的当前值
  • 现值指数;
  • 数组被减少;

如果减少顺序对你来说很重要,你应该知道你也可以访问它,.reduceRight()它的作用与前一种方法完全相同,但是从右侧开始向后移动。🔙

.find[索引]()

在数组中查找特定元素可能是一项艰巨的任务,除非它是第一个或最后一个。这时,ES6 添加的.find()方法就派上用场了。它只需接受处理标准参数集的检查函数,并返回给定数组中第一个匹配的值undefined,否则返回其他值。

const arr = [1,2,3,4];
const matched = arr.find(num => num % 2 === 0); // 2

Enter fullscreen mode Exit fullscreen mode

还有一种.findIndex()方法,与第一个方法类似,它使用匹配函数来查找值,但返回的是其索引而不是原始值。它可以与.indexOf()或进行比较.lastIndexOf(),后者也可以用来检索与给定值匹配的第一个值和最后一个值的索引,但它的表达能力不如.findIndex()匹配函数那么强。😑

const arr = [1,2,3,4];
const matched = arr.findIndex(num => num % 2 === 0); // 1

Enter fullscreen mode Exit fullscreen mode

最后要注意的是 - 如果您.indexOf()仅使用它来检查给定数组中是否存在值,请考虑使用.includes()(ES6 功能) - 它返回一个布尔值,并且比其替代方案具有更好的性能

。每一个()

有些人可能以为.every()只需对给定数组的每个元素运行提供的函数,但这种命名可能会产生误导。实际上,.every()Indeed 会在每个元素上运行一个函数,但只是为了检查它们是否遵循提供的准则,并最终返回一个正确的布尔值。检查函数提供了标准的参数集。👌

const arr = [1,2,3,4];
const isIncremental = arr.every((num, idx, arr) => {
    const previousIdx = idx - 1;
    if(previousIdx >= 0){
        return num === arr[previousIdx] + 1
    } else {
        return true;
    }
}); // true

Enter fullscreen mode Exit fullscreen mode

.copyWithin()

对于某些人来说,在单个数组的边缘复制数据可能会感觉有点复杂且毫无意义。但是,凭借其卓越的性能🌠(尤其是在其TypedArrays对应版本中),此方法提供了一种快速移动数组元素的好方法!在这里,您可以传递 1 到 3 个参数:

  • 复制数据将从其粘贴到的目标索引。由于不会改变.copyWithin()源数组的长度,因此元素将被替换,旧数据将被删除。
  • 标记要复制的数据开始的起始索引(默认为 0 - 数组的开头
  • 标记要复制的数据的结束(不包括提供的索引)的结束索引(默认为给.length定数组的末尾)
const arr = [1,2,3,4];
arr.copyWithin(0,2); // Array.copyWithin() mutates the source array
arr; // [3,4,3,4]

Enter fullscreen mode Exit fullscreen mode

。种类()

.sort()是这些方法之一,其功能显然与名称所暗示的完全一致。在本例中,它只是对数组进行排序。它可以提供或不提供比较函数。默认情况下,所有值都将转换为字符串,并按UTF-16编码🌐 值递增排序,即数字从小到大,字符串按字母顺序排序。您还可以提供一个函数,该函数接收两个元素作为单独的参数进行比较。此比较函数应返回一个数字,然后该数字将用于以给定方式对提供的值进行排序:

  • 如果函数返回小于 0 的数字,则第一个参数提供的值优先;
  • 如果函数返回的数字等于 0,则值将保持不变(规范实际上并不保证);
  • 如果函数返回大于 0 的数字,则第二个参数提供的值优先;
const arr = [1,2,3,4];
arr.sort((num1, num2) => {
    return num2 - num1;
}); 
// Array.sort() mutates the source array

Enter fullscreen mode Exit fullscreen mode

。一些()

.some()是一种类似于 的方法.every()。它检查源数组中的元素是否满足某些规则(以检查函数的形式提供),并最终返回布尔值。不同之处在于只.some()需要一个元素☝ 满足测试即可返回正值,而 ☝ 则.every()需要所有元素都满足测试。它可以帮助您检查是否至少有一个值具有给定的属性。提供的测试函数接收一组标准参数(元素、其索引和源数组)。

const arr = [1,2,3,4];
arr.some((num) => {
    return num % 5 === 0;
}); // false

Enter fullscreen mode Exit fullscreen mode

迭代

惊喜!😲 事实上,数组 API 中只有一个方法专门用于执行迭代!对于那些只使用 和类似方法迭代源数组的人来说,这真是一个好消息.map().reduce()这个任务只有一个方法,因此,它应该受到尊重和熟知。

.forEach()

.forEach(),顾名思义,它会对源数组的每个元素进行迭代。提供一个接收标准参数集的函数,它会对给定数组的每个元素运行该函数。🔁

const arr = [1,2,3,4];
arr.forEach((num) => {
    console.log(num); // 1/2/3/4
})
Enter fullscreen mode Exit fullscreen mode

各种各样的

除了上述所有类别之外,数组 API 还提供了其他一些方法。以下列举了一些鲜为人知常用的方法,但在某些特殊情况下可能会派上用场。

.entries()

.entries()是三个迭代器对象返回方法中的第一个。数组迭代器对象,或者说可迭代对象,是一种简单的结构,可以使用for... of循环进行自然迭代,并且只有一个.next()方法在迭代时被调用。直接调用时,它会返回一个包含和属性的对象,这两个属性分别指示*当前值*和迭代是否完成。⏳ 再次调用时,它会返回数组中的下一个值,并且该过程将持续到源数组末尾,此时属性将被设置为truevaluedonedone

我们方法返回的迭代器的值将以键值对.entries()(数组)的形式存在,其中第一个元素表示当前索引,第二个元素表示相应的值。你可以将它(以及稍后讨​​论的其他方法)与它们对应的对象进行比较。像or 这样的函数(不在原型上)当然比它们的数组兄弟更受欢迎,但它们的功能类似。Object.entries()Object.keys()

const arr = ["a","b","c","d"];
const iterable = arr.entries();
iterable.next(); // {value: [0, "a"], done: false}
iterable.next().value; // [1, "b"]
iterable.next().value; // [2, "c"]
iterable.next(); // {value: [3, "d"], done: true}

Enter fullscreen mode Exit fullscreen mode

迭代完成后,无法重新启动。唯一的方法是使用相同的方法创建一个新的可迭代对象。

但是这种方法的用例是什么呢?嗯,该.next()方法确实能让你更好地控制数组的迭代方式✊。此外,当需要同时访问元素的值和索引时,返回的键值对.entries()肯定很有用。但是,在这种情况下,也许标准对象映射(我在上一篇文章中讨论过)会更适合你。

.keys()

既然已经涵盖了可迭代对象的所有复杂性,那么还有两个类似于.entries()-.keys()和 的方法.values()。顾名思义,第一个方法返回一个可迭代对象,其值等于源数组的索引(也称为键)。🔢 它返回的不是键值数组,而是表示数组元素索引的数字

const arr = ["a","b","c","d"];
const iterable = arr.keys();
iterable.next(); // {value: 0, done: false}
// ...

Enter fullscreen mode Exit fullscreen mode

.值()

.values()方法再次返回可迭代对象。这次它的值等于源数组元素的值

const arr = ["a","b","c","d"];
const iterable = arr.values();
iterable.next(); // {value: "a", done: false}
// ...

Enter fullscreen mode Exit fullscreen mode

.toString()

我想讨论的最后一个方法是.toString()。它存在于 JS 对象、函数、字符串、数字、数组等等中!甚至可能存在于每个 JS 对象中(万物皆对象)!但我认为,尽管它无处不在,但该.toString()方法仍然没有得到应有的重视。

该方法的核心.toString()是将数组转换为字符串。返回值的形式为方括号,数组元素紧密排列,并以逗号分隔。

const arr = [1,2,3,4];
const str = arr.toString(); // "[1,2,3,4]"

Enter fullscreen mode Exit fullscreen mode

但它最大的好处就是不需要直接调用!

const arr = [1,2,3,4];
const str = `${arr}`; // "[1,2,3,4]"

Enter fullscreen mode Exit fullscreen mode

这样,每次需要将值转换为字符串(例如字符串文字或连接)时,都会调用此方法。此外,您还可以自由地使用自己的实现更改此方法,这使得您不仅可以返回自定义字符串,还可以在执行此操作时执行某些操作!✨相信我——这可以让你做一些非常有趣的技巧

阵列时间!

好了,以上就是我个人挑选的一些最有趣、最值得一看的数组 API 方法!你都了解了吗?我知道内置 API 很容易被遗忘,从而导致我们去寻找一些根本不需要解决的问题的解决方案。希望这篇文章至少能帮助你解决其中的一些问题。😀

那么,你觉得这篇文章怎么样?请在评论区写下你的看法,并在下方留言告诉我你是否喜欢它!另外,请关注我的 推特🐦我的脸书主页,并考虑查看我的个人博客,以便及时了解本博客的最新内容⏱。一如既往,感谢你阅读这篇文章,我们下期再见!✌

鏂囩珷鏉ユ簮锛�https://dev.to/areknawo/discovering-array-api-goodies-1m26
PREV
完整的 Monorepo 设置教程 你说 Monorepo?那么,它值得吗?如何搭建 Monorepo?Lerna 太棒了!Monorepos……😵
NEXT
Deno - 为什么如此受关注?什么是 Deno?Node.js 对比:为什么如此受关注?总结