前言
最近研究zepto源码的时候发现一些非常好用的数组方法,这些就是es5新增的数组方法,而w3c这些网站并没有这些方法介绍,可能是太久没更新维护了。总结了一下,给这些方法分了类,大体如下:
5个迭代方法:forEach()、map()、filter()、some()、every();
2个索引方法:indexOf() 和 lastIndexOf();
2个归并方法:reduce()、reduceRight();
迭代方法
这些方法都接收两个参数,第一个参数是一个函数,它接收三个参数,数组当前项的值、当前项在数组中的索引、数组对象本身。第二个参数是执行第一个函数参数的作用域对象,也就是上面说的函数中this所指向的值。注意,这几种方法都不会改变原数组。
1、forEach(即遍历)
var arr = [1, 2, 3, 4];
[4, 3, 2, 1].forEach(function (item, index, array) {
console.log('item', item); //打印当前值(4,3,2,1)
console.log('index', index); //打印索引值(0,1,2,3)
console.log('array', array); //[4, 3, 2, 1]
console.log('this', this); //如果有arr参数值的话,打印[1, 2, 3, 4],否则打印window对象
}, arr);
var arr2 = [5, 6, 7, 8];
[].forEach.call(arr, function (item, index, array) {
console.log('item', item); //打印当前值(1,2,3,4)
console.log('index', index); //打印索引值(0,1,2,3)
console.log('array', array); //[1, 2, 3, 4]
console.log('this', this); //如果有arr2参数值的话,打印[5, 6, 7, 8],否则打印window对象
}, arr2);
这里把方法的作用域对象也讲下,后面的例子就不重复了。如果这第2个可选参数不指定,则使用全局对象代替(在浏览器是为window),严格模式下甚至是undefined。
而且删除数组中某项后,forEach遍历数组也有点不同。
var array = [1, 2, 3];
delete array[1]; // 移除 2
console.log(array); // 打印"1,,3"
console.log(array[1]);//打印undefined
console.log(array.length); //长度仍然是3
array.forEach(alert); // 弹出的仅仅是1和3
array.forEach(console.log); //打印1 0 [1,,3]、3 2 [1,,3]
2、map(映射)
var data = [1, 2, 3, 4];
var arrayOfSquares = data.map(function (item) {
return item * item;
});
console.log(arrayOfSquares); //打印[1, 4, 9, 16]
map是一一对应的关系,如果没有return的话,则返回一个跟原数组相同长度的undefined数组。在实际使用的时候,我们可以利用map方法方便提取对象数组中的特定属性值们。
var users = [
{name: "张三", "age": "16"},
{name: "李四", "age": "17"},
{name: "王五", "age": "18"}
];
var names = users.map(function (user) {
return user.name;
});
console.log('names', names); //打印names ["张三", "李四", "王五"]
3、filter(过滤)
var users = [
{name: "张三", "age": "16"},
{name: "李四", "age": "17"},
{name: "王五", "age": "18"}
];
var fullAgeUser = users.filter(function (user) {
if (user.age >= 17) {
return user;
}
});
console.log('fullAgeUser', JSON.stringify(fullAgeUser)); //打印fullAgeUser [{"name":"李四","age":"17"},{"name":"王五","age":"18"}]
过滤同map相似,不过没有return的话,返回的数组就没有该项,常用于筛选部分符合条件的数组。
4、some(某项满足)
var users = [
{name: "张三", "age": "16"},
{name: "李四", "age": "17"},
{name: "王五", "age": "18"}
];
var fullAgeResult = users.some(function (user) {
console.log(JSON.stringify(user));
return user.age >= 17;
});
console.log('fullAgeResult', fullAgeResult); //打印true
some遍历数组,如果有某项满足条件,则跳出循环不再执行,返回true;否则返回false。
5、every(所有项满足)
var users = [
{name: "张三", "age": "16"},
{name: "李四", "age": "17"},
{name: "王五", "age": "18"}
];
var fullAgeResult = users.every(function (user) {
console.log(JSON.stringify(user));
return user.age >= 16;
});
console.log('fullAgeResult', fullAgeResult); //打印true
every遍历数组,如果某项没有满足条件,则跳出循环不再执行,返回false;如果所有项都满足则返回true。
索引方法
1、indexOf(索引)
indexOf方法在字符串中一直都用,数组这里的indexOf方法很类似:array.indexOf(searchElement[, fromIndex])。
var array = [1, 4, 6, 2, 4];
console.log(array.indexOf(4, "x")); // 1 ("x"被忽略)
console.log(array.indexOf(4, "2")); // 4 (从2号位开始搜索)
console.log(array.indexOf(3)); // -1 (未找到)
console.log(array.indexOf("4")); // -1 (未找到,因为4 !== "4")
返回整数索引值,如果没有匹配(进行严格匹配),返回-1。fromIndex可选,表示从这个位置开始搜索,若缺省或格式不合要求,使用默认值0,fromIndex使用字符串数值也是可以的,例如”3”和3都可以,没有进行严格匹配。
2、lastIndexOf(倒序查找)
var array = [1, 6, 4, 2, 4];
console.log(array.lastIndexOf(4)); //4
console.log(array.lastIndexOf(4, 1)); //-1
倒序查找,如果制定了fromIndex,则从fromIndex往前查找。
归并方法
1、reduce(合并)
var result = [1, 2, 3, 4].reduce(function (previous, current, index, array) {
console.log('previous', previous); //1,3,6
return previous + current;
});
console.log(result); //10
result = [1, 2, 3, 4].reduce(function (previous, current, index, array) {
console.log('previous', previous); //3,4,6,9
return previous + current;
}, 3);
console.log(result); //13
array.reduce(callback[, initialValue]),如果不存在initialValue的话,则第一个previous是数组第一项。最后两个参数为索引值index以及数组本身。
执行过程:
// 初始设置
previous = initialValue = 3, current = 1
// 第一次迭代
previous = (3 + 1) = 4, current = 2
// 第二次迭代
previous = (4 + 2) = 6, current = 3
// 第三次迭代(退出循环)
previous = (6 + 3) = 9, current = 4
实际应用当中,我们可以实现二维数组的扁平化(即转化为一维数组)。
var matrix = [
[1, 2],
[3, 4],
[5, 6]
];
console.log(matrix.reduce(function (prev, curr) { //[1, 2, 3, 4, 5, 6]
return prev.concat(curr);
}));
2、reduceRight(倒序合并)
var matrix = [
[1, 2],
[3, 4],
[5, 6]
];
console.log(matrix.reduceRight(function (prev, curr) { //[5, 6, 3, 4, 1, 2]
return prev.concat(curr);
}));
与reduce极为相似。
--------------------------------------------------------------------------------------------------
ES6中新增的方法有:
- Array.isArray(): 判断是否是一个数组
- forEach(): 对数组进行遍历操作
- map(): 遍历数组,可以对数组的每一项做相关的操作,并且会返回一个新数组,不会改变原来数组
- filter(): 遍历数组的每一项,如果数组中某个元素满足某个条件,将当前的元素push到一个新数组中
- some(): 把数组的每一项和某个条件进行 对比,如果有一个符合条件,就会返回 true,否则返回false
- every():把数组的每一项和某个条件进行 对比,如果全部符合条件,就会返回 true,否则返回false
下面对上面的方法一一进行详解:
1、Array.isArray():
var s = '代码测试 Array.isArray';
console.log(Array.isArray(s))// false
var arr = [];
console.log(Array.isArray(arr));// true
var obj = {};
console.log(Array.isArray(obj));// false
2、forEach():
var arr = ['12','13','-12','0','8'];
// 遍历数组,并且给每一项都加上 10
// index 代表数组的下标,value 代表数组元素的值, array 就是遍历的数组本身
arr.forEach(function(value,index,array){
//console.log("%c" + index + '======' + value,'color:red;')
// 加上 10
arr[index] =String( Number(value) + 10 );
});
console.log(arr);// ["22", "23", "-2", "10", "18"]
var arr = [1,2,,3,5];
arr.forEach(function(index,val){
});
console.log(arr);//[1, 2, empty, 3, 5];
var arr = [1,2,,3,5];
var obj={};
arr.forEach(function(val,index){
return obj[index] = val
});
console.log(obj);//{0: 1, 1: 2, 3: 3, 4: 5}
3、map():
注意:map 的函数中 需要用 return 返回值
var arr = [12,34,4,-1,10,66];
// 每个值 加上10
// map 循环数组以后会生成一个 新的数组,所以需要定义一个变量 接受处理后的数据
var newArr = arr.map(function(value,index,array){
return value + 10
});
console.log(newArr);// [22, 44, 14, 9, 20, 76]
// map 不使用return
var arr = [1,2,,3,5];
var a = arr.map(function(index,val){
});
console.log(a);//[undefined, undefined, empty, undefined, undefined]
//使用return
var arr = [1,2,,3,5];
var a = arr.map(function(index,val){
return index;
});
console.log(a);//[1, 2, empty, 3, 5]
4、filter():
var arr = [59,60,90,50,32,78];
//需要挑选出 值大于 60 的元素
var newArr = arr.filter(function(value,index){
return value > 60
});
// filter 和 map 处理后会返回一个 新的数组,如果没有 满足的条件的元素 会返回 一个空数组
console.log(newArr);// [90,78]
//需要挑选出 值大于 99 的元素
var newArr2 = arr.filter(function(value,index){
return value > 99
});
console.log(newArr2);// 返回值是 []
5、some():
var arr = [12,13,44,45,78];
var res = arr.some(function(value,index){
// 判断 arr 中是否 有大于 80 的元素
return value > 80
});
console.log(res);// false
// 我们还可以 利用 some 这个方法 去判断 数组中是否包含某个元素
var res2 = arr.some(function(value,index){
// 判断 数组中是否有 12
return value === 12
});
console.log(res2);// true
6、every():
var arr = [12,13,14,44,56,9];
// 判断 是否 所有的元素 都大于 10
var res = arr.every(function(value,index){
return value >10
});
console.log(res);// false
小结:除了 forEach() 不需要用变量接受返回值,其他剩下遍历 数组的方法都要 用一个变量去接收;forEach 是对原数组进行操作,其他的都不会 破坏原数组