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的让页面控件不可用的实现代码
Apr 27 Javascript
jQuery 表格插件整理
Apr 27 Javascript
jquery Mobile入门—多页面切换示例学习
Jan 08 Javascript
基于JavaScript实现继承机制之原型链(prototype chaining)的详解
May 07 Javascript
js 动态给元素添加、移除事件的实现方法
Jul 19 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
Jan 20 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
Mar 14 Javascript
vue2中使用sass并配置全局的sass样式变量的方法
Sep 04 Javascript
微信小程序使用gitee进行版本管理
Sep 20 Javascript
Phaser.js实现简单的跑酷游戏附源码下载
Oct 26 Javascript
layui 点击重置按钮, select 并没有被重置的解决方法
Sep 03 Javascript
vue实现下载文件流完整前后端代码
Nov 17 Vue.js
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
中国第一家无线电行
2021/03/01 无线电
php 大数据量及海量数据处理算法总结
2011/05/07 PHP
PHP根据IP判断地区名信息的示例代码
2014/03/03 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
PHP开发实现快递查询功能详解
2019/04/08 PHP
XENON基于JSON变种
2010/07/27 Javascript
node.js中的fs.exists方法使用说明
2014/12/17 Javascript
在AngularJS应用中实现一些动画效果的代码
2015/06/18 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
H5移动端适配 Flexible方案
2016/10/24 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
2017/01/11 Javascript
详解微信小程序 wx.uploadFile 的编码坑
2017/01/23 Javascript
vue 请求后台数据的实例代码
2017/06/22 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
js键盘事件实现人物的行走
2020/01/17 Javascript
在Echarts图中给坐标轴加一个标识线markLine
2020/07/20 Javascript
关于angular浏览器兼容性问题的解决方案
2020/07/26 Javascript
Python 列表(List)操作方法详解
2014/03/11 Python
基于python中staticmethod和classmethod的区别(详解)
2017/10/24 Python
Python Numpy 数组的初始化和基本操作
2018/03/13 Python
分享8个非常流行的 Python 可视化工具包
2019/06/05 Python
详解Python中的测试工具
2019/06/09 Python
感知器基础原理及python实现过程详解
2019/09/30 Python
python实现飞机大战小游戏
2019/11/08 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
基于CSS3实现图片模糊过滤效果
2015/11/19 HTML / CSS
海蓝之谜英国官网:La Mer英国
2020/01/15 全球购物
小学语文教师年度考核个人总结
2015/02/05 职场文书
外贸采购员岗位职责
2015/04/03 职场文书
2015年效能监察工作总结
2015/04/23 职场文书
幼儿园小班工作总结2015
2015/04/25 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
MySQL CHAR和VARCHAR该如何选择
2021/05/31 MySQL
Python实现简繁体转换
2021/06/07 Python
解决linux下redis数据库overcommit_memory问题
2022/02/24 Redis
Redis实现订单过期删除的方法步骤
2022/06/05 Redis