JavaScript数组方法的错误使用例子


Posted in Javascript onSeptember 13, 2018

1. 不要使用Array.indexOf,使用Array.includes

“如果你要在数组中查找元素,使用Array.indexOf!”。记得在我学习JavaScript课程时候,有这样一句话。这句话没错,确实可以这么使用!

根据MDN文档:“Array.indexOf会返回被查找元素第一个匹配的位置的下标。”因此,如果后面需要用到这个索引,Array.indexOf是一个很好的解法。但是,我们要解决的问题是:查找数组中是否包含某个元素。这是一个Yes/No的问题,是一个返回布尔类型的真假问题。因此,我建议使用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

2. 不要使用Array.filter,使用Array.find

Array.filter是一个很有用的函数,它返回一个满足过滤条件的新数组。正如其名字表达的含义,它是用来做过滤的。

但是,如果我们知道我们要的结果只有一个元素的时候,我就不建议使用它了。比如,如果我们的回调函数定义用一个唯一的ID来过滤,那么结果必然唯一了。在这个情况下,Array.filter会返回只有一个元素的数组。因为既然能通过一个特定的ID来查找,我们已经确定只有一个元素了,那么使用数组就没有意义。

另外,我们再来聊聊性能问题。为了返回所有匹配的元素,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' }

3. 不要使用Array.find,使用Array.some

我承认我犯过很多次错误。后来,一个很要好的朋友让我去看看MDN的文档,说有更好的解决方案。这个情况和刚刚提到的Array.indexOf/Array.includes很像。

在前面的例子中,我们看到Array.find接受一个过滤函数,返回满足的元素。那么,如果我们要查找一个数组是否包含某个元素的时候,Array.find是否是最佳的方案呢?可能不是,因为它返回的是元素具体的值,而不是布尔值。

我推荐大家使用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

4. 不要使用Array.map和Array.filter组合,使用Array.reduce

Array.reduce有点难以理解!但是,如果我们每次在同时使用Array.filter和Array.map的时候,你是否觉察到需要点东西,对不?

我的意思是:我们对整个数组循环了2遍。第一次是过滤返回一个新的数组,第二次通过map又构造一个新的数组。我们使用了两个数组方法,每一个方法都有各自的回调函数,而且Array.filter返回的数组以后再也不会用到。

为了避免低效率,我建议使用Array.reduce。同样的结果,更优雅的代码!请看下面的例子:‘'

'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'] }
// ]
Javascript 相关文章推荐
jquery CSS选择器笔记
Mar 29 Javascript
jQuery 下拉列表 二级联动插件分享
Mar 29 Javascript
Javascript的时间戳和php的时间戳转换注意事项
Apr 12 Javascript
JS 精确统计网站访问量的实例代码
Jul 05 Javascript
js中的referrer返回上一页使用介绍
Sep 26 Javascript
jQuery中slideUp 和 slideDown 的点击事件
Feb 26 Javascript
微信小程序 canvas API详解及实例代码
Oct 08 Javascript
JavaScript中Hoisting详解 (变量提升与函数声明提升)
Aug 18 Javascript
vue-cli axios请求方式及跨域处理问题
Mar 28 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
Feb 14 jQuery
vue 父组件通过$refs获取子组件的值和方法详解
Nov 07 Javascript
基于js实现数组相邻元素上移下移
May 19 Javascript
vue仿element实现分页器效果
Sep 13 #Javascript
区别JavaScript函数声明与变量声明
Sep 12 #Javascript
详解js中Array的方法及技巧
Sep 12 #Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
Sep 12 #Javascript
angularjs下ng-repeat点击元素改变样式的实现方法
Sep 12 #Javascript
angularjs的单选框+ng-repeat的实现方法
Sep 12 #Javascript
vue服务端渲染缓存应用详解
Sep 12 #Javascript
You might like
php curl的深入解析
2013/06/02 PHP
smarty简单分页的实现方法
2014/10/27 PHP
PHP中如何使用session实现保存用户登录信息
2015/10/20 PHP
SSO单点登录的PHP实现方法(Laravel框架)
2016/03/23 PHP
PHP实现针对日期,月数,天数,周数,小时,分,秒等的加减运算示例【基于strtotime】
2017/04/19 PHP
jQuery DOM操作小结与实例
2010/01/07 Javascript
读jQuery之十 事件模块概述
2011/06/27 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
JS+css 图片自动缩放自适应大小
2013/08/08 Javascript
jquery制作搜狐快站页面效果示例分享
2014/02/21 Javascript
JavaScript中的fontsize()方法使用详解
2015/06/08 Javascript
测试IE浏览器对JavaScript的AngularJS的兼容性
2015/06/19 Javascript
JavaScript检测字符串中是否含有html标签实现方法
2015/07/01 Javascript
AngularJS实现用户登录状态判断的方法(Model添加拦截过滤器,路由增加限制)
2016/12/12 Javascript
canvas 弹幕效果(实例分享)
2017/01/11 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
IE9 elementUI文件上传的问题解决
2018/10/17 Javascript
微信小程序实现星星评价效果
2018/11/02 Javascript
如何在Vue中使用CleaveJS格式化你的输入内容
2018/12/14 Javascript
JS事件流与事件处理程序实例分析
2019/08/16 Javascript
JS实现悬浮球只在一侧滑动并且是横屏状态下
2020/08/19 Javascript
[27:02]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第三场
2014/05/24 DOTA
使用BeautifulSoup爬虫程序获取百度搜索结果的标题和url示例
2014/01/19 Python
python字符串对其居中显示的方法
2015/07/11 Python
详解python中executemany和序列的使用方法
2017/08/12 Python
详解python-图像处理(映射变换)
2019/03/22 Python
基于python实现高速视频传输程序
2019/05/05 Python
树莓派4B+opencv4+python 打开摄像头的实现方法
2019/10/18 Python
opencv-python的RGB与BGR互转方式
2020/06/02 Python
python用Configobj模块读取配置文件
2020/09/26 Python
附答案的Java面试题
2012/11/19 面试题
辛德勒的名单观后感
2015/06/03 职场文书
教师旷工检讨书
2015/08/15 职场文书
爱护公物主题班会
2015/08/17 职场文书
2016年教师节贺卡寄语
2015/12/04 职场文书