常用数组方法
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);
> 6
const 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
```javascript
var 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 写法
```javascript
var 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