常用数组方法
JavaScript中对数组有四种常见的操作:map、filter、reduce、find。
map(映射)
Array.prototype.map() 将提供的转换应用于原始数组的每个元素,创建一个新数组。结果数组长度和原数组相同,并且根据提供的函数转换了元素。
const arr = [1, 2, 3];const double = x => x * 2;arr.map(double);> [2, 4, 6]
filter(过滤)
Array.prototype.filter() 使用过滤函数创建新数组,以仅保留 true 基于该函数返回的元素。结果是一个等于或小于原始数组长度的数组,其中包含与原始数组相同元素的子集。
const arr = [1, 2, 3];const isOdd = x => x % 2 === 1;arr.filter(isOdd);> [1, 3]
reduce(汇总)
Array.prototype.reduce() 在每个数组元素上运行函数,以生成(减少它)单个值。根据提供的reducer函数,结果可以是任何类型,例如整数,对象或数组。
const arr = [1, 2, 3];const sum = (x, y) => x + y;arr.reduce(sum, 0);> 6const increment = (x, y) => [...x, x[x.length - 1] + y];arr.reduce(increment, [0]);> [0, 1, 3, 6]
find(查找)
Array.prototype.find() 返回匹配器函数返回的第一个元素true。结果是原始数组中的单个元素。
const arr = [1, 2, 3];const isOdd = x => x % 2 === 1;arr.find(isOdd);> 1
应用
从对象数组中取出特定字段组成新数组
var arr = [{'id': '1','name': 'img1','imgUrl': './img1.jpg',},{'id': '2','name: 'img2','imgUrl': './img2.jpg',},{'id': '3','name': 'img3','imgUrl': './img3.jpg',}];// 取imgUrl生成新数组var imgList = arr.map(x => {return x.imgUrl})
从对象数组中按id查找对象
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]// 获取对应的foo属性myArray.find(x => x.id === '45').foo;> "bar"// 查找索引myArray.findIndex(x => x.id === '45');> 1// 获取匹配的元素myArray.filter(x => x.id === '45');> [{id: "45", foo: "bar"}]// 获取一组foo属性myArray.filter(x => x.id === '45').map(x => x.foo);> ["bar"]
reduce() 求笛卡尔积
const arr1 = ['1', '2', '3'];const arr2 = ['a', 'b'];// 用来作为运算的二维数组const arr3 = [arr1, arr2, ['x', 'y']]const result = arr3.reduce((last, el) => {const arr = [];// last:上次运算结果// el:数组中的当前元素last.forEach(e1 => {el.forEach(e2 => {arr.push(e1 + "_" + e2)})})return arr});console.log(result);
ES5 实现
map
- ES5 实现map ```javascript var numbersA = [1,2,3,4,5,6]; var numbersB = [];
for(var i = 0; i < numbersA.length; i++){ numbersB.push(numbersA[i] * 2); } console.log(numbersB)
- ES6```javascriptvar numbersB = numbersA.map(item => {return item * 2;})console.log(numbersB)
filter
ES5 实现filter
var persons = [{name:"小王",type:"boy",city:"广西",age:15,height:170},{name:"小美",type:"girl",city:"北京",age:16,height:180},{name:"小高",type:"girl",city:"湖南",age:18,height:175},{name:"小刘",type:"boy",city:"河北",age:20,height:177}]// ES5,假定要拿person数组对象中类型为boy的对象var filterPersons = [];for(var i = 0; i < persons.length; i++){if (persons[i].type == "boy"){filterPersons.push(persons[i]); // 若是想要拿到对象的键值,直接persons[i].属性名}}console.log(filterPersons);
ES6
var filterPersons = persons.filter( item => {return item.type === "boy";})
find
ES5 实现 find ```javascript / 找到learnWebs数组对象中name值为segementdefault / var learnWebs = [ {name:”segmentdefault”}, {name:”MDN”}, {name:”stackoverflow”}, {name:”v2ex”}, {name:”w3cplus”}, {name:”segmentdefault”} ]
var learnWeb = []; for(var i = 0;i < learnWebs.length; i++){ if(learnWebs[i].name === “segmentdefault”){ learnWeb.push(learnWebs[i]); //break;// 若不加break,都会走完一遍for循环 } } console.log(learnWeb);
- ES6 写法```javascriptvar learnWeb = learnWebs.find(item => {return item.name === "segmentdefault";})
性能比较
性能上:for循环 > forEach > map
可读性:forEach/map > for循环
区别
for循环是按顺序遍历,按照下标索引的方式进行读取访问元素的,随机访问。
而forEach/map等是使用iterator迭代器进行遍历,先取到数组中的每一项的地止放入到队列中,然后按顺序取出队里的地址来访问元素。
可以使用 console.time() 以及 console.timeEnd() 进行测试。
扩展
forEach,map,filter,find 还有 every, some 方法都是不改变原有数组的,
- forEach方法没有返回值,默认返回值为undefined,所以它不支持链式调用
- map,filter方法会返回一个新的数组。
- find方法返回的根据迭代器函数结果boolean值,若结果为真则返回指定的元素,若无则返回undefined
改变原有数组的有:增加(push,unshift),删除(pop,shift),reverse(颠倒,sort(排序),splice
