首页>前端教程>JavaScript教程

JavaScript基础7:数组Arrays常用的迭代方法

这些新增的方法只有IE9或者Edge及chrome等现代浏览器才支持,IE8及以下就不支持了。不过,老的东西肯定是要被抛弃的,学习新东西是常态。

技术总是一波接一波更新,所以持续学习是技术人必须的技能。不然很容易被拍死在沙滩上。

数组迭代方法对每个数组项都要进行操作。

1、forEach()

为每个数组元素调用一次函数。这个函数可以称之为“回调函数”。返回值是undefined。不会修改原始数组,但是在callback中可能更改原始数组。

arr.forEach(callback[,thisArg]);

callback:

为数组中每个元素执行的函数,该函数接收三个参数:

  • currentValue 数组中正在处理的当前元素。

  • index  可选 数组中正在处理的当前元素的索引。

  • array  可选  forEach() 方法正在操作的数组。

thisArg:

可选  当执行回调函数时用作 this 的值(参考对象)。

forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除或者未初始化的项将被跳过。

以前都是用for循环遍历数组,现在可以改用forEach()了,前提是浏览器支持。

var arr=['成都','重庆','北京','上海'];
var city=[];
for(let i=0;i<arr.length;i++){
    city.push(arr[i]);
}

//改成forEach()
arr.forEach(function(value){
    city.push(value);
})
function logArray(value,index){
    console.log('arr['+index+']='+value)
}
var arr=[1,2,,4,5,,7];
arr.forEach(logArray); //arr[0]=1 arr[1]=2 arr[3]=4 arr[4]=5 arr[6]=7

forEach 遍历的范围在第一次调用 callback 前就会确定。调用 forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()),之后的元素将被跳过。而且,不能中止遍历,除非报错。

var arr=[1,2,-Infinity,'2',50];

arr.forEach(function(num,index){
if(num===-Infinity){
arr.splice(index,2);
}
console.log(num); //1,2,-Infinity
})

arr.forEach(function(num,index){
if(num===-Infinity){
arr.splice(index,2,Infinity,10);
}
console.log(num); //1,2,-Infinity,10,50
})

在DOM中,用querySelectorAll()返回的是NodeList节点集合,并不是真的数组,而是一种类数组。低版本不支持forEach()函数,所以升级浏览器吧。可以不用for循环了。

var oP=document.querySelectorAll('p');
console.log(oP); //NodeList(5) [p, p, p, p, p]
oP.forEach(function(obj,index){
obj.innerHTML=index;
});

具体参考:Array.prototype.forEach()

2、map()

和forEach()几乎一样的使用方法,参数都是一样的,差别在于map()函数会返回一个新数组

var arr=[2,4,8,10];
var newArr=arr.map(function(x){
    return x/2;
})
console.log(newArr); //[1, 2, 4, 5]

map里面的回调函数也可以不是自定义的函数,可以是现有的内置函数。

var num=[2,15,'12','a'];
var newNum=num.map(isNaN); //isNaN是一个函数,所以不能加()。 [false, false, false, true]

var num=['1',2,'2.2e2',2.5e-3];
var newNum=num.map(Number);//[1, 2, 220, 0.0025]

但是要注意,有些函数有多个参数,可能会导致问题。

比如:parseInt(numString, [radix]),如果用这个函数的话,就会把数组的索引值当成了进制数。

numString:必选项。要转换为数字的字符串。

radix :  可选项。在 2 和 36 之间的表示 numString 所保存数字的进制的值。如果没有提供,则前缀为 '0x' 的字符串被当作十六进制,前缀为 '0' 的字符串被当作八进制。所有其它字符串都被当作是十进制的。

parseInt 方法返回与保存在 numString 中的数字值相等的整数。如果 numString 的前缀不能解释为整数,则返回 NaN(而不是数字)。

var num=[1,2,10,4,5,6,12,16,7];
var newNum=num.map(parseInt); // [1, NaN, 2, NaN, NaN, NaN, 8, 13, 7]
parseInt(10,2);// 2
parseInt('0xffffff',16); //16777215
parseInt(7,8); //7
parseInt(2,10);//2

目前,最新的浏览器,NodeList类数组也不支持map()方法,但是还是可以利用call()方法实现。

obj1.(method).call(obj2,argument1,argument2)

call()方法就是把obj1的方法拿给obj2用。argument是obj1方法的参数。

<label><input type="checkbox" name="hobby" id="c1" value="编程">编程</label>
<label></label><input type="checkbox" name="hobby" id="c2" checked value="美术">美术</label>
<label></label><input type="checkbox" name="hobby" id="c3" checked value="阅读">阅读</label>
<script>
var oCheckbox=document.querySelectorAll("input:checked"); //NodeList(2) [input#c2, input#c3]
var values=Array.prototype.map.call(oCheckbox,function(obj){
return obj.value;
})
console.log(values); //["美术", "阅读"]
</script>

这里有个动图很好的解释了map()的工作原理,来源于:https://www.w3cplus.com/web/web-tips-15.html

3、filter()

filter是过滤,筛选的意思,顾名思义,应该是数组元素挨个进行某个条件测试,然后返回成功通过的新数组

var newArray = arr.filter(callback(element[, index[, array]])[,thisArg])

callback

用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。

后面的参数和前面的map()等迭代函数意思一样。

返回值是一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。

var age=[12,18,25,45,60,17,22];
var result=age.filter(function(value){
return value>=18 && value<=45;
})
console.log(result); //[18, 25, 45, 22]
var arr=[2,8,'a','12',-12,null,undefined,,'',NaN];

function myFilter(value){
return  value!==undefined&&typeof(value)==='number'&&!isNaN(value)&&value!==0;
}
var newArr=arr.filter(myFilter);
console.log(newArr); // [2, 8, -12]

4、every()

检测数组内所有元素是否通过测试,全部通过返回true,任何一个不通过,返回false。如果是一个空数组,返回true。返回布尔值。

感觉就是一竿子打翻一船人啊,或者说一颗老鼠屎坏了一锅汤 :)

function isBig(value) {
return value >= 60 && value <= 100;
}
var result = [85, 75, 98, 53, 60, 105].every(isBig);
console.log(result); //false

也可以简写成箭头函数:
[85, 75, 98, 53, 60, 105].every(value=>value>=60&&value<=100)

5、some()

有至少一个数组元素通过了测试,就返回true。返回的是一个布尔值。

  • 如果一个元素满足条件,返回true,且后面的元素不再被检测

  • 所有元素都不满足条件,则返回false

  • 不会改变原始数组

  • 不会对空数组进行检测;数组为空的话,直接返回false

function isBiggerThan10(item){
    return item>10;    
}
[12,10,8,7,-5].some(isBiggerThan10); //true;

检查某个元素是否存在:

var myname=['老赵','小何','小王'];
function isExit(arr,val){
return  arr.some(function(value){
return value===val;
})
}
console.log(isExit(myname,'老赵')); //true

6、includes()

确定数组的条目中是否包含某个值,并根据需要返回true或false没有回调函数,只有两个参数。

ES6的新方法,Edge14及以上才支持。

arr.includes(valueToFind[,fromIndex])

注意:比较字符的时候,区分大小写。

[1, 2, 3].includes(2);     // true
[1, 2, 3].includes(4);     // false
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true
[1, 2, 3].includes(3, -4); // true
[1, 2, NaN].includes(NaN); // true

该方法的第二个参数表示搜索的起始位置,默认为0。

如果fromIndex大于或等于数组的长度,则返回false。将不搜索数组。

如果FromIndex为负数,则按照array.length + fromIndex先计算。计算出的索引将用作数组中开始搜索valueToFind的位置。如果计算的索引小于或等于-1*array.length,则将搜索整个数组。

// array length is 3
// fromIndex is -100// 
computed index is 3 + (-100) = -97
var arr = ['a', 'b', 'c'];
arr.includes('a', -100); // true
arr.includes('b', -100); // true
arr.includes('c', -100); // true
arr.includes('a', -2); // false

以前查找使用indexOf(),但是不能判断出NaN。

[NaN].indexOf(NaN);// -1

现在includes()使用samevaluezero算法来确定是否找到给定的元素。所以可以得到NaN,而且+0,-0,0都当成0,false不能当成0。

[NaN].includes(NaN);// true
[-0].includes(0);// true

如果为了兼容IE9,可以利用some()写一个includes()的简易版。

const contains = (() =>
Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value)
)();
contains(['foo', 'bar'], 'baz'); // => false

7、find()

arr.find(callback(element[, index[, array]])[, thisArg])

找到第一个符合条件测试的元素,并返回,如果没有找到,返回undefined.

Edge12及以上支持,IE9不支持。

const myArr=[1,2,3,4,5,6];
var v=myArr.find(value=>value>4);
console.log(v);// 5

const myArr=[1,2,3,4,5,6];
var v=myArr.find(value=>value>40);
console.log(v);// undefined

8、findIndex()

arr.findIndex(callback(element[, index[, array]])[, thisArg])

和find()相似,只不过返回的是第一个通过测试的元素的索引值没有返回-1

const students=[
{
id:1,
s_name:'小王'
},
{
id:2,
s_name:'小赵'
},
{
id:3,
s_name:'小李子'
}
]
var i=students.findIndex(value=>value.id==2);
console.log(i); //1
var n=students.findIndex(value=>value.id==5);
console.log(n); //-1

数组的方法太多了,有些方法具有相似的功能,但是还是要看几个关键点,功能有什么区别,参数是什么,返回的值是什么,有没有修改原数组等。只有关联起来理解才不会混乱。

var arr1=[NaN,undefined,null,2,0];
console.log(arr1.indexOf(NaN)); //-1
console.log(arr1.includes(NaN)); //true
console.log(arr1.find(function(value){ //null
return value===null;
}));
console.log(arr1.findIndex(function(value){ //1
return value===undefined;
}))
console.log(arr1.filter(function(value){ // [null, 2, 0]
return value>=0;
}))

9、reduce()

reduce() 方法对数组中的每个元素执行一个回调函数中提供的reducer函数(升序执行),将其结果汇总为单个返回值。

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

reducer 函数接收4个参数:

  • Accumulator (acc) (累计器) 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(初始值)。

  • Current Value (cur) (当前值) 数组中正在处理的元素。

  • Current Index (idx) (当前索引)  数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则为1。

  • Source Array (src) (源数组)  调用reduce()的数组

 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。

initialValue 可选 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

返回函数累计处理的结果.

回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
  return accumulator + currentValue;}, 0); 
  //6
var initialValue = 0;var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;},initialValue)
    console.log(sum) 
    // logs 6
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
  function(a, b) {
    return a.concat(b);
  },
  []);
  // flattened is [0, 1, 2, 3, 4, 5]

数组的方法实在太多,看图:

array.jpg

数组全部的方法:MDN:Array

点赞


1
保存到:

相关文章

发表评论:

◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

Top