当前位置:   article > 正文

JS遍历数组的十五种方法

js遍历数组

一、循环遍历
for循环,也是最常见的。

可以使用临时变量,将长度缓存起来,避免重复获取数组长度,当数组较大时优化效果才会比较明显。

  1. // arr 是要遍历的数组
  2. // arr[i] 是遍历的数组的元素
  3. // i 是数组的元素对应的下标(索引号)
  4. for (var i = 0; i < arr.length; i++) {
  5.   console.log(arr[i]);
  6. }
  7. let arr = [1, 2, 3, 4];
  8. for (let i = 0; i < arr.length; i++) {
  9.     arr[i] = arr[i] + 1; // 直接通过索引修改原数组的值
  10. }
  11. console.log(arr); // [2,3,4,5]
  12. let list = [{sex: '男'},{sex: '女'},{sex: '男'}];
  13. for (let i = 0; i < list.length; i++) {
  14.    list[i].sex = '女';
  15. }
  16. console.log(list); // [{sex: '女'}, {sex: '女'}, {sex: '女'}]


二、for of遍历

  1. // arr 遍历的数组
  2. // item 遍历的数组的元素
  3. for(var item of arr) {
  4.   console.log(item);
  5. }
  6. let arr = [1, 2, 3, 4];
  7. for(var item of arr) {
  8.   console.log(item);
  9. } // 1 2 3 4


三、for in遍历

  1. // arr 遍历的数组
  2. // item 遍历的数组的元素
  3. for(var index in arr) {
  4. console.log(item);
  5. }
  6. let arr = [1, 2, 3, 4];
  7. for(var index in arr) {
  8. console.log(item);
  9. }
  10. // 0 1 2 3

四、forEach()遍历


这种方法只是使处理需要循环的数组变得更加容易,因为你不必像通常那样写出笨重而长的for循环语句

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数,没有返回值,原数组不变

forEach() 对于空数组是不会执行回调函数的。

注意和map方法区分。

  1. // arrObj 需要遍历的数组
  2. // item 遍历出的每一个元素
  3. // index 元素对应的下标
  4. // self 数组本身
  5. // 无返回值
  6. arrObj.forEach(function(item,index,self) {
  7.   console.log(item);
  8. });
  9. let arr = [1, 2, 3, 4];
  10. arr.forEach(item => {
  11.     item = item * 2;
  12. });
  13. console.log(arr); // [1, 2, 3, 4]   原数组保持不变


五、map()映射遍历


map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值,并没有改变原来的数组。

map() 方法按照原始数组元素顺序依次处理元素。

注意:map() 不会对空数组进行检测。

  1. // arrObj 需要遍历的数组
  2. // item 遍历出的每一个元素
  3. // index 元素对应的下标
  4. // self 数组本身
  5. // 有返回值
  6. // newArr 新返回的数组
  7. // 数组元素个数不变,但是按照一定的条件转换
  8. arrObj.map(function(item,index,self) {
  9.   return item*2;
  10. });
  11. let arr = [1, 2, 3, 4];
  12. let newArr = arr.map(item => {
  13.     return item * 2;
  14. });
  15. console.log(arr); // [1, 2, 3, 4]   原数组保持不变
  16. console.log(newArr); // [2, 4, 6, 8] 返回新数组

for 与 forEach、map的区别

  • 在固定长度或者长度不需要计算的时候for循环效率高于foreach和map,for循环中可以通过break终止。
  • 在不确定长度或者计算长度有损性能的时候用foreach和map比较方便

forEach、map的区别
相同点

  •         都是循环遍历数组中的每一项
  •         forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项),index(索引值),arr(原数组)
  • 匿名函数中的this都是指向window
  • 只能遍历数组
  • 都不会改变原数组

不同点:

  • map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值
  • forEach方法不会返回新数组

性能:

  •         for > forEach > map
  •         for 循环当然是最简单的,因为它没有任何额外的函数调用栈和上下文
  •         forEach 其次,因为它其实比我们想象得要复杂一些。它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能;
  •         map 最慢,因为它的返回值是一个等长的全新的数组,数组创建和赋值产生的性能开销很大。

六、filter()过滤遍历


将所有元素进行判断,将满足条件的元素作为一个新的数组返回, 原数组不变。

注意:filter() 不会对空数组进行检测。

  1. // arrObj 需要遍历的数组
  2. // item 遍历出的每一个元素
  3. // index 元素对应的下标
  4. // self 数组本身
  5. // 有返回值,返回满足某个条件的元素构成的数组
  6. // 数组元素个数可能改变,按照一定的条件返回
  7. arrObj.filter(function(item,index,self) {
  8.     return item < 3;
  9. });
  10. let arr = [1, 2, 3, 4];
  11. let newArr = arr.filter(item => {
  12.     return item < 3;
  13. });
  14. console.log(arr); // [1, 2, 3, 4]   原数组保持不变
  15. console.log(newArr); // [1, 2]   返回新数组


七、find()遍历


数组中的每个元素都调用一次函数执行。

当数组中的元素在测试条件时返回true,find()返回符合条件的元素,之后的值不会再执行函数;如果没有符合条件的元素则返回undefined,原数组不变。

注意::find() 对于空数组,函数是不会执行的。

  1. let arr = [1, 2, 3, 4];
  2. let newArr1 = arr.find(item => {
  3.     return item > 2;
  4. });
  5. let newArr2 = arr.find(item => {
  6.     return item > 5;
  7. });
  8. console.log(arr); // [1, 2, 3, 4]   原数组保持不变
  9. console.log(newArr1); // 3  返回第一个符合条件的元素
  10. console.log(newArr2); // undefined  没有符合条件的元素则返回undefined


八、findIndex()遍历


遍历数组,找到第一个符合条件的元素,并返回该元素;否则,返回-1。

不改变原数组。

  1. let fruits= ['苹果', '梨子', '桃子', '西瓜', '哈密瓜'];
  2. let vegetables= [{
  3.   id: 1,
  4.   name: '花椰菜'
  5. },{
  6.   id: 2,
  7.   name: '青椒'
  8. },{
  9.   id: 3,
  10.   name: '土豆'
  11. },{
  12.   id: 4,
  13.   name: '西红柿'
  14. }];
  15. // fruits 需要遍历的数组
  16. // item 数组的元素
  17. // index 元素对应的下标
  18. // arr 数组本身
  19. let findIndexFru = fruits.findIndex(function(item, index, arr){
  20.   return index > 5;
  21. });
  22. console.log(findIndexFru); // -1
  23. let findIndexVeg = vegetables.findIndex(function(item, index, arr){
  24.   // 返回 遍历子对象
  25.   console.log(item.name);
  26.   // // 返回 遍历索引值
  27.   console.log(index);
  28.   // 返回 所有子对象
  29.   console.log(arr);
  30.   return item.id> 2;
  31. });
  32. console.log(findIndexVeg);


九、indexOf()遍历


从前往后遍历数组,找到第一个符合条件的项,并返回该项。否则返回-1。

不改变原数组。

字符串也有此方法,功能类似。

  1. let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
  2. // fruits 需要遍历的数组
  3. // item 需要搜索的值
  4. // index 数组中的的索引值,可以为负数,代表相对数组末尾的偏移量
  5. let indexOfFru = fruits.indexOf('桃子');
  6. console.log(indexOfFru); // 2


十、lastIndexOf()遍历


从后往前遍历数组,找到第一个符合条件的项,并返回该项。否则返回-1。

不改变原数组。

字符串也有此方法,功能类似。

  1. let fruits= ['苹果', '梨子', '桃子', '西瓜', '哈密瓜'];
  2. // fruits 需要遍历的数组
  3. // item 需要搜索的值
  4. // index 数组中的的索引值,可以为负数,代表相对数组末尾的偏移量
  5. let lastIndexOfFru = fruits.lastIndexOf('西瓜');
  6. console.log(lastIndexOfFru); // 3


十一、every()遍历


将所有元素进行判断,返回一个布尔值,原数组不变。

如果所有元素都满足判断条件,则返回true,否则为false。

注意:every() 不会对空数组进行检测。

  1. // arrObj 需要遍历的数组
  2. // item 遍历出的每一个元素
  3. // index 元素对应的下标
  4. // self 数组本身
  5. // 有返回值,检测数组里的每一个值是否满足指定条件,如果有一个值不满足,返回false,剩余的值不再进行检测;如果所有的值都满足,则返回true
  6. arrObj.every(function(item,index,self) {
  7.   return item < 3;
  8. });
  9. let arr = [1, 2, 3, 4];
  10. let newArr1 = arr.every(item => {
  11.     return item > 2;
  12. });
  13. let newArr2 = arr.every(item => {
  14.     return item < 5;
  15. });
  16. console.log(arr); // [1, 2, 3, 4]   原数组保持不变
  17. console.log(newArr1); // false
  18. console.log(newArr2); // true


十二、some()遍历


将所有元素进行判断, 返回一个布尔值, 原数组不变。

如果存在元素满足判断条件,则返回true,若所有元素都不满足判断条件,则返回false。

判断条件注意和every方法区分。

  1. // arrObj 需要遍历的数组
  2. // item 遍历出的每一个元素
  3. // index 元素对应的下标
  4. // self 数组本身
  5. // 有返回值,检测数组里的每一个值是否满足指定条件,如果有一个值满足,返回true,剩余的值不再进行检测;如果所有的值都不满足,则返回false
  6. arrObj.some(function(item,index,self) {
  7. return item < 4;
  8. });
  9. let arr = [1, 2, 3, 4];
  10. let newArr1 = arr.some(item => {
  11. return item > 2;
  12. });
  13. let newArr2 = arr.some(item => {
  14. return item > 5;
  15. });
  16. console.log(arr); // [1, 2, 3, 4] 原数组保持不变
  17. console.log(newArr1); // true
  18. console.log(newArr2); // false

十三、reduce高阶函数(迭代(累加器))

  1. // arrObj 需要遍历的数组
  2. // total 初始值或计算结束后的返回值
  3. // item 遍历出的每一个元素
  4. // index 元素对应的下标
  5. // self 数组本身
  6. // 有返回值,返回计算结束后的total值
  7. arrObj.reduce(function(total,item,index,self){
  8. },初始值);

十四、reduceRight()遍历


接收一个函数作为累加器(accumulator),数组中的每个值(从右到左)开始缩减,最终为一个值。

第二个参数作为第一次调用的a的值。

  1. let arrNum = [2, 4, 6, 8, 10];
  2. // 累加
  3. let sum = arrNum.reduceRight(function(x, y){
  4.   return x + y;
  5. });
  6. console.log(sum); // 30
  7. // 累乘
  8. let multiple = arrNum.reduceRight(function(x, y){
  9.   return x * y;
  10. });
  11. console.log(multiple); // 3840
  12. // 求最大值
  13. let bigger = arrNum.reduceRight(function(x, y){
  14.   return x > y ? x : y;
  15. });
  16. console.log(bigger); // 10


十五、遍历器机制


截止到ES6,JavaScript 已经拥有了数组、对象、Map集合和Set集合这样四种数据结构。

为了统一和简化遍历这四种数据结构的操作,ES6引入了遍历器机制。

ES6 规定,可遍历的对象都具有Symbol.iterator 属性,这个属性指向一个函数,就是当前对象默认的遍历器生成函数。

这个遍历器生成函数大致的模样可以用ES5 语法模拟出来:这个函数返回一个next() 方法,每调用next() 方法,都会返回数据结构的当前成员的信息。

具体来说,就是返回一个包含value和done两个属性的对象。

其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

在ES6 中,已经默认为绝大多数內建的数据结构提供了遍历器,不需要自己去创建。

  1. // keys()方法:默认遍历器,其值为集合中的所有键名。
  2. // values()方法:默认遍历器,其值为集合中的所有值。
  3. // entries()方法:默认遍历器,其值为所有成员的键值对。
  4. const arr = ["A", "B", "C"];
  5. console.log([...arr.keys()]); // [0, 1, 2]
  6. console.log([...arr.values()]); // ["A", "B", "C"]
  7. console.log([...arr.entries()]); // [[0, "A"],[1, "B"],[2, "C"]]
  8. const set = new Set(arr);
  9. console.log([...set.keys()]); // ["A", "B", "C"]
  10. console.log([...set.values()]); // ["A", "B", "C"]
  11. console.log([...set.entries()]); // [["A", "A"],["B", "B"],["C", "C"]]
  12. const map = new Map().set("name", "Tom").set("age", 19);
  13. console.log([...map.keys()]); // ["name", "age"]
  14. console.log([...map.values()]); // ["Tom", 19]
  15. console.log([...map.entries()]); // [["name", "Tom"],["age", 19]]


每个数据结构都有一个默认的遍历器,例如数组的默认遍历器是values(),在没有明确指定遍历器的情况下,这些数据结构都会使用默认的遍历器。

我们可以通过检测对象的Symbol.iterator属性来判断对象是否拥有遍历器。

  1. const arr = ["A", "B", "C"];
  2. console.log(typeof arr[Symbol.iterator] === "function"); // true
  3. console.log(arr[Symbol.iterator]); // function values() { ... }
  4. const set = new Set(arr);
  5. console.log(typeof set[Symbol.iterator] === "function"); // true
  6. console.log(set[Symbol.iterator]); // function values() { ... }
  7. const map = new Map().set("name", "Tom").set("age", 19);
  8. console.log(typeof map[Symbol.iterator] === "function"); // true
  9. console.log(map[Symbol.iterator]); // function entries() { ... }


原生具备遍历器的对象:

数组、Map集合、Set集合、字符串、arguments和 NodeList(节点列表)

对象(Object)默认是不可遍历的,我们可以通过Object.keys()、Object.values()和Object.entries() 方法把对象变成数组,使其拥有遍历器;或者直接为对象添加Symbol.iterator 属性来自定义遍历器。

  1. const obj = {
  2.   name: "Tom",
  3.   age: 19
  4. }
  5. console.log(typeof Object.entries(obj)[Symbol.iterator] === "function"); // true
  6. console.log([...Object.entries(obj)]); // [["name", "Tom"],["age", 19]]

十六、以下为那些循环可以终止图 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/94153
推荐阅读
相关标签
  

闽ICP备14008679号