百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

JavaScript中的数组(Array)方法你真的了解吗?

wptr33 2025-03-14 21:28 10 浏览

在过去的几个月,我发现我的拉取请求中存在四个完全相同的 JavaScript 错误。于是我写了这篇文章,总结了如何在 JavaScript 中正确使用地使用 Array 的方法!

用 Array.includes 代替 Array.indexOf

“如果你要在数组中查找元素,请使用 Array.indexOf”。我记得在学习 JavaScript 的时候,在教材中读到这样的一句话。毫无疑问,这句话是真的!

MDN 文档写道,Array.indexOf 将“返回第一次出现给定元素的索引”。因此,如果我们稍后要在代码中使用这个返回的索引,那么使用 Array.indexOf 找到索引就对了。

但是,如果我们只想知道数组是否包含某个值,该怎么办?这似乎是一个是与否的问题,或者说是一个布尔值问题。对于这种情况,我建议使用返回布尔值的 Array.includes。

 'use strict';
 
 const characters = [
   'ironman',
   'black_widow',
   'hulk',
   'captain_america',
   'hulk',
   'thor',
 ];
 
 console.log(characters.indexOf('hulk'));
 // 2
 console.log(characters.indexOf('batman'));
 // -1
 
 console.log(characters.includes('hulk'));
 // true
 console.log(characters.includes('batman'));
 // false
 
 使用 Array.find 而不是 Array.filter

Array.filter 是一个非常有用的方法。它接受一个回调函数作为参数,基于一个包含所有元素的数组创建出一个新的数组。正如它的名字一样,我们使用这个方法来过滤元素,获得更短的数组。

但是,如果回调函数只能返回一个元素,那么我就不推荐使用这个方法,例如使用回调函数来过滤唯一 ID。在这种情况下,Array.filter 将返回一个只包含一个元素的新数组。我们的意图可能是通过查找特定的 ID 找到数组中包含的唯一值。

我们来看看这个方法的性能。要返回与回调函数匹配的所有元素,Array.filter 必须遍历整个数组。此外,我们假设有数百个元素可以满足回调参数,那么过滤后的数组会非常大。

为了避免这种情况,我建议使用 Array.find。它需要一个像 Array.filter 一样的回调函数作为参数,并返回满足回调函数的第一个元素的值。此外,只要找到第一个满足回调函数的元素,Array.find 就会停止,无需遍历整个数组。通过 Array.find 来查找元素,我们可以更好地理解我们的意图。

 'use strict';
 
 const characters = [
   { id: 1, name: 'ironman' },
   { id: 2, name: 'black_widow' },
   { id: 3, name: 'captain_america' },
   { id: 4, name: 'captain_america' },
 ];
 
 function getCharacter(name) {
   return character => character.name === name;
 }
 
 console.log(characters.filter(getCharacter('captain_america')));
 // [
 //   { id: 3, name: 'captain_america' },
 //   { id: 4, name: 'captain_america' },
 // ]
 
 console.log(characters.find(getCharacter('captain_america')));
 // { id: 3, name: 'captain_america' }

用 Array.some 代替 Array.find

我承认这个错误我犯了很多次。然后,一位善良的朋友告诉我,最好可以先参考 MDN 文档。这与上面的
Array.indexOf/Array.includes 非常相似。

在前面的例子中,我们看到 Array.find 需要一个回调函数作为参数,并返回一个元素。如果我们想要知道数组是否包含某个值,Array.find 是最好的解决方案吗?可能不是,因为它返回的是一个元素值,而不是一个布尔值。

对于这种情况,我建议使用 Array.some,它返回所需的布尔值。另外,从语义上看,Array.some 表示我们只想知道某个元素是否存在,而不需要得到这个元素。

 'use strict';
 
 const characters = [
   { id: 1, name: 'ironman', env: 'marvel' },
   { id: 2, name: 'black_widow', env: 'marvel' },
   { id: 3, name: 'wonder_woman', env: 'dc_comics' },
 ];
 
 function hasCharacterFrom(env) {
   return character => character.env === env;
 }
 
 console.log(characters.find(hasCharacterFrom('marvel')));
 // { id: 1, name: 'ironman', env: 'marvel' }
 
 console.log(characters.some(hasCharacterFrom('marvel')));
 // true

使用 Array.reduce 而不是链接 Array.filter 和 Array.map

让我们面对现实吧,Array.reduce 不容易理解。事实确实如此!但是,如果我们使用 Array.filter 和 Array.map 的组合,感觉缺少了什么,对吧?

我的意思是,我们遍历了两次数组。第一次过滤数组并创建一个较短的数组,第二次又基于 Array.filter 获得数组创建一个包含新值的数组。为了获得我们想要的新数组,我们使用了两个 Array 方法。每个方法都有自己的回调函数和一个用不到的数组——由 Array.filter 创建的那个数组。

为了避免这种性能损耗,我的建议是使用 Array.reduce。结果是一样的,代码却更简单! 我们可以使用 Array.reduce 进行过滤,并将目标元素添加到累加器中。累加器可以是递增的数字、要填充的对象、要连接的字符串或数组。

在我们的例子中,因为之前使用了 Array.map,所以我建议使用 Array.reduce 将满足条件的数组元素加入到累加器中。在下面的示例中,根据 env 值的具体情况,我们将它添加到累加器中或保持累加器不变。

 'use strict';
 
 const characters = [
   { name: 'ironman', env: 'marvel' },
   { name: 'black_widow', env: 'marvel' },
   { name: 'wonder_woman', env: 'dc_comics' },
 ];
 
 console.log(
   characters
     .filter(character => character.env === 'marvel')
     .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
 );
 // [
 //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
 //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
 // ]
 
 console.log(
   characters
     .reduce((acc, character) => {
       return character.env === 'marvel'
         ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
         : acc;
     }, [])
 )
 // [
 //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
 //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
 // ]

OK,这篇文章就写到这里咯.这篇文章比较短,但是看似这些方法都比较简单,但是要能够灵活运用,提高效率还是要多练习的.

大家有什么疑问或者更好的理解也可以在评论区留言哦,一起讨论


相关推荐

吸顶大法 -- UWP中的工具栏吸顶的实现方式之一

如果一个页面中有很长的列表/内容,很多应用都会在用户向下滚动时隐藏页面的头,给用户留出更多的阅读空间,同时提供一个方便的吸顶工具栏,比如淘宝中的店铺页面。下面是一个比较简单的实现,如果有同学有更好的实...

C# ListView实现在日志中添加图片

ListView想在日志中添加图片,需要配合ImageList控件使用。1、在ListView控件中添加ImageList,视图选择Details2、添加列,有几张图片显示就添加几列ListViewI...

安卓里面优秀的第三方插件gitHub文件

pinned-section-listview这个列表是正确实施其他实现缺失很多功能。这些都是快速滚动页眉和页脚点击固定部分除此之外,它不产生任何不必要的视图、布局等很瘦。xUtils3...

android使用greendao来保存数据

有时我们的数据属于保存到数据库,对于Android应用和IOS应用,我们一般都会使用SQLite这个嵌入式的数据库作为我们保存数据的工具。由于我们直接操作数据库比较麻烦,而且管理起来也非常的麻烦,所以...

常见电脑桌面问题,你知多少

(一)桌面图标无法删除出现一些不认识的图标1.关闭正常运行且需要删除的程序;2.运行杀毒软件进行扫毒处理;3.系统欢迎或者重装系统;4.通过软件自带的卸载程序或者第三方软件(QQ管家、360)进行卸载...

独家|React Native 无限列表的优化与实践

导语本文介绍了在使用ReactNative开发过程中,如何对无限列表组件进行技术选型,如何使用RecyclerListView组件对无限列表进行性能优化,如何解决无限列表与标签页搭配使用时的内存...

深入浅出SlidingMenu

如果想直接查看源码的话可以从我的Github上下载查看:https://github.com/zhanghuijun0/demo-for-android/tree/master/SlidingMenu...

就问你酷不酷 定制自己的动态壁纸

虽然壁纸可以经常更换,但总是看着静态壁纸难免让人乏味。下面就教你如何设置动态壁纸,让你的桌面动起来炫起来。WindowsXP系统虽已退休多年,但在国内仍有大量的忠实用户,那我们就从它说起。其实Win...

安卓的ViewPager概述

一、ViewPager概述1、定义与用途:...

书评 | 9 年码龄工程师读 Android 经典

...

Flet 手机app界面设计,导航和路由,在多个界面之间自由跳转

前面的几篇文章,基本讲清楚了Flet界面设计,但都是“单个界面”。在实际项目中,肯定需要设计“多个界面”啊,多个界面直接怎么导航呢?也就是Flet的路由功能,这是Flet开发的必备技术。依然保...

Android指示器,轮播与循环轮播

AndroidUILibs之CircleIndicator1.说明CircleIndicator,顾名思义,圆形指示器,只一个可以用来做轮播的第三方库。2.配置在模块的build.gradle...

Shopee新手指南:Shopee卖家中心用户界面介绍

1.Shopee各站点前台网页链接:2.Shopee各站点后台网页链接3.ShopeeAPP下载:安卓版下载链接:https://pan.baidu.com/s/1eSp8M1k#list/path...

Django 官方推荐的姿势:类视图

作者:HelloGitHub-追梦人物在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个论坛,通常其首页都是展示一系列的文章列表或者帖子列表。对处理...

ViewPager介绍和使用说明

ViewPager类提供了多界面切换的新效果。新效果有如下特征:...