ES5和ES6数组遍历方法详解

在ES5中常用的10种数组遍历方法:

1、原始的for循环语句
2、Array.prototype.forEach数组对象内置方法
3、Array.prototype.map数组对象内置方法
4、Array.prototype.filter数组对象内置方法
5、Array.prototype.reduce数组对象内置方法
6、Array.prototype.some数组对象内置方法
7、Array.prototype.every数组对象内置方法
8、Array.prototype.indexOf数组对象内置方法
9、Array.prototype.lastIndexOf数组对象内置方法
10、for...in循环语句

ES6中新增加了一种:

1.for...of循环语句

ES5三种数组循环示例如下:

原始for循环语句

Example1

var a = [1,2,3];
for(var i=0;i<a.length;i++){console.log(a[i]);  //结果依次为1,2,3
}

代码解读:原始for循环的优点在于大家都比较熟悉,容易理解,劣势是写起来比较繁琐,需要定义额外更多的变量,所以一下是针对于原始for循环的改良的两种写法:
Example1:写法改良版

var a = [1,2,3];
for(var i=a.length;i--;){console.log(a[i]);  //结果依次为3,2,1
}

Example2:性能改良版

var a = [1,2,3];
for(var i = 0,len=a.length; i < len; i++) {console.log(a[i]);  //结果依次为1,2,3
}

注意:以上代码可以写成这样呢,如果懵逼了的话接着看原始for循环的解读,我们都知道for循环包含三个语句块——>for(语句1;语句2;语句3){被执行的代码},其中,语句1一般为变量定义语句(不仅可以只定义一个变量哦),在循环开始前执行,而且只执行一次语句2定义循环的是否继续执行的条件,同样也是在循环开始前执行,语句1之后执行,每次重新开始循环都会再次执行语句3则在循环结束之后执行,并且每次结束的时候都会再次执行,这里要注意的是如果被执行的代码中途return出来了那是不会再执行一次语句3的,所以以上代码解释如下:因为i--这个语句在每次循环开始前都会再次先用 i 是true和false来判断是否继续执行,这里同样要注意的是由于i----i的区别,这里由于是i--所以会先判断i的值再去做‘减减’的操作,所以这里最后如果打印 i 的值,会发现其实是-1

数组内置方法Array.prototype.forEach

Example

var a = [1,2,3];
a.forEach(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3],该参数貌似没什么用
})

代码解读:forEach方法最大的好处就是便于使用,而且不用定义额外的参数变量,但是从效率以及性能角度来说它是劣于原始for循环的,而且也不能强制return结束循环,原因如下:

**forEach循环**一看就是通过**回调函数**来提供参数的,而回调函数在JS中是**闭包**的一种,闭包的作用是用来生成**私有作用域**的,所以,每一个回调函数都是一个**独立的作用域**,都拥有自己独立的存储空间,互不影响,而且内部变量还不及时释放,这也就是为什么在能不用闭包的情况下就不要用闭包的原因,而在闭包中return的话,也只是在当前回调函数中返回了,可是forEach中的其他的回调函数(闭包)仍然存在,所以,导致return是没办法结束循环的。下面写一个forEach循环实现例子供大家参考理解:

Example

Array.prototype.forEachCopy = function(callback){var arr =  this;for(var i=0;i<arr.length;i++){callback(arr[i],i,this);}
}
var a = [1,2,3];
a.forEachCopy(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3]
})

数组内置方法Array.prototype.map

Example

var a = [1,2,3];
var b = a.map(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3]return value+1;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 2, 3, 4 ]

代码解读:map和forEach不同,在forEach中return语句是没有任何效果的,而map则可以改变当前循环的值,并且最终会返回一个新的被改变过值之后的数组(map如果不用return就和forEach一样了),由于这个特性,map一般用来处理需要修改某一个数组的值。map和forEach在其他的方面都是一样的,也不能return结束循环等特性,下面写一个map循环实现的例子供大家参考理解:
Example

Array.prototype.mapCopy = function(callback){var arr =  this;var arrCopy = [];for(var i=0;i<arr.length;i++){var cbValue = callback(arr[i],i,this);arrCopy.push(cbValue);}return arrCopy;
}
var a = [1,2,3];
var b = a.mapCopy(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3]return value+1;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 2, 3, 4 ]

数组内置方法Array.prototype.filter

Example

var a = [1,2,3];
var b = a.filter(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3]if(value === 3){return false;}return true;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 1,2 ]

代码解读:filter和map不同,map目的是为了改变值,而filter目的是为了去掉不要的值,在循环的时候如果返回的是false那么就表示本次循环的不添加该值,返回true则相反是表示要添加到新建的数组中,下面写一个filter循环实现例子供大家参考:
Example

Array.prototype.filterCopy = function(callback){var arr =  this;var arrCopy = [];for(var i=0;i<arr.length;i++){var cbValue = callback(arr[i],i,this);if(cbValue){arrCopy.push(arr[i]);}}return arrCopy;
}
var a = [1,2,3];
var b = a.filterCopy(function(value,key,arr){console.log(value)    // 结果依次为1,2,3console.log(key)      // 结尾依次为0,1,2console.log(arr)      // 三次结果都为[1,2,3]if(value === 3){return false;}return true;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 1,2 ]

数组内置方法Array.prototype.reduce

Example

var a = [1,2,3];
var b = a.reduce(function (count, value,key,arry) {console.log(count);   // 结果依次为0,1,3console.log(value);   // 结果依次为1,2,3console.log(key);     // 结果依次为0,1,2console.log(arry)     // 三次结果都为[1,2,3]return count + value;
},0);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b)          // 结果为6

代码解读:reduce的不同之处在于累加,和其他几个内置方法不同的地方,它的第二个参数不是this对象,而是初始累加值(如果不设置的话数组会乱掉),而且回调函数的的个数也不同,比其他的多了一个,而且还在在开始的多加了一个参数,第一个参数记录的是上一次循环的累加值,下面写一个reduce循环实现例子供大家参考:
Example

Array.prototype.reduceCopy = function(callback,countInit){var arr =  this;for(var i=0;i<arr.length;i++){var cbValue = callback(countInit,arr[i],i,this);countInit = cbValue;}return countInit;
}
var a = [1,2,3];
var b = a.reduceCopy(function (count, value,key,arry) {console.log(count);   // 结果依次为0,1,3console.log(value);   // 结果依次为1,2,3console.log(key);     // 结果依次为0,1,2console.log(arry)     // 三次结果都为[1,2,3]return count + value;
},0);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b)          // 结果为6

数组内置方法Array.prototype.some

Example

var a = [1,2,3];
var b = a.some(function(value,key,arry){console.log(value);   // 结果依次为1,2console.log(key);     // 结果依次为0,1console.log(arry);    // 两次次结果都为[1,2,3]return value===2;
})
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为true

代码解读:some的不同之处在它返回的布尔值,它的作用有点像filter,不过它的目的不是为了筛选返回数组,而是为了筛选该数组是否有满足你要的值,而且找到符合条件的值返回了一次true之后就不会再继续执行了,下面写一个some循环实现例子供大家参考:

Example

Array.prototype.someCopy = function(callback,countInit){var arr =  this;var isBool = false;for(var i=0;i<arr.length;i++){var cbValue = callback(arr[i],i,this);if(cbValue){isBool = true;return isBool}}return isBool;
}
var a = [1,2,3];
var b = a.someCopy(function(value,key,arry){console.log(value);   // 结果依次为1,2console.log(key);     // 结果依次为0,1console.log(arry);    // 两次次结果都为[1,2,3]return value===2;
})
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为true

数组内置方法Array.prototype.every

Example

var a = [1,2,3];
var b = a.every(function(value,key,arry){console.log(value);   // 结果依次为1,2console.log(key);     // 结果依次为0,1console.log(arry);    // 两次次结果都为[1,2,3]return value===2;
})
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为false

代码解读:其实从看例子可以看出来,some和every作用是一样的,只不过some当找到之后返回的是true,而every找到之后返回的是false而已,下面写一个every循环实现例子供大家参考:

Example

Array.prototype.everyCopy = function(callback){var arr =  this;var isBool = true;for(var i=0;i<arr.length;i++){var cbValue = callback(arr[i],i,this);if(cbValue){isBool = false;return isBool}}return isBool;
}
var a = [1,2,3];
var b = a.everyCopy(function(value,key,arry){console.log(value);   // 结果依次为1,2console.log(key);     // 结果依次为0,1console.log(arry);    // 两次次结果都为[1,2,3]return value===2;
})
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为false

数组内置方法Array.prototype.indexOf

Example

var a = [1,2,3];
var b = a.indexOf(2);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为1

代码解读:对于indexOf方法来说,在数组循环过程中会和传入的参数比对,如果是比对成功,那么终止循环,返回对比成功的下标,下面写一个indexOf循环实现例子供大家参考:

Example

Array.prototype.indexOfCopy = function(value){var arr =  this;var index = -1;for(var i=0;i<arr.length;i++){if(arr[i] === value){index = i;return index}}return index;
}
var a = [1,2,3];
var b = a.indexOfCopy(2);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b);         // 结果为1

数组内置方法Array.prototype.lastIndexOf

Example

var a = [1,2,3,1];
var b = a.lastIndexOf(1);
console.log(a);         // 结果为[ 1, 2, 3, 1 ]
console.log(b);         // 结果为1

代码解读:lastIndexOf方法和indexOf作用一致,但查找方向不同,indexOf是正向查找,lastIndexOf是你像查找,找到之后返回成功的下标,下面写一个lastIndexOf循环实现例子供大家参考:

Example

Array.prototype.lastIndexOf = function(value){var arr =  this;var index = -1;for(var i=arr.length;i--;){if(arr[i] === value){index = i;return index}}return index;
}
var a = [1,2,3,1];
var b = a.lastIndexOf(1);
console.log(a);         // 结果为[ 1, 2, 3 , 1 ]
console.log(b);         // 结果为3

小结:对于以上8个数组的内置方法,forEach方法仅仅只是为了循环,并不可以帮你做额外的事情;map方法相当于在循环的时候你告诉数组当前遍历的这个值需要改成什么样,那么它就会最后给什么样的数组;filter方法相当于在循环的时候数组遍历一个个对象,并问你这个是不是你要找的值,如果你说是,他就会给你返回一个到新的数组中,不是他就会剔除;reduce方法相当于循环遍历对象做统计(累加或者累减之类的);some和every方法相当于在遍历的时候拿着一个个对象问你这个是不是你找的,只要你说了一遍是,那么他就会给你分别返回的是true和false;indexOf和lastIndexOf方法相当于你告诉它你要找什么值,找到之后立马返回给你它的门牌号。

循环语句for...in

Example

var a = [1,2,3];
for(var key in a){console.log(key); //结果为依次为0,1,2
}
var b = {0:1,1:2,2:3};
for(var key in b){console.log(key); //结果为依次为0,1,2
}

代码解读:从结果得知,for...in遍历数组的时候是遍历数组的下标值,而在遍历对象的时候遍历的是key值,所以猜想,数组在JS中,本质上也是一个以键值对形式存在的对象,而为了证明这点,我们做如下一个例子的实验:

var a = [];
a['b'] = 2;
console.log(a);     //结果为[ b: 2 ]
console.log(a[0]);  //结果为undefined

我们发现数组的下标不在对应相应位置的值了,由此可以证明在JS中数组其实本质上就是一个以下标为key值的对象。
当然对于for...in循环语句本身而言,它是一个浅度遍历对象的循环语句,值遍历第一层节点(当然对象中设置不可枚举的属性的除外)。
Example

var a = {b:{c:2},d:{c:4}};
for(var key in a){console.log(key); //结果为依次为b,d
}

ES6循环for...of语句

Example

var a = [1,2,3];
for(var value of a){console.log(value)  // 结果依次为1,2,3
}

代码解读:for...of语句看着有点像for...in语句,但是和for...in语句不同的是它不可以循环对象,只能循环数组。

ES5和ES6数组遍历方法详解相关推荐

  1. js 数组遍历方法详解(map、filter、find、findIndex、reduce)

    目录 前言 map map是什么 map方法的结构及入参 语法糖 map一般不改变原数组 filter 说明 例子 find 和 findIndex 说明 例子 reduce 说明 例子 尾言 前言 ...

  2. linux jq 遍历数组,jquery 遍历数组 each 方法详解

    JQuery拿取对象的方式 $('#id') :通过元素的id $('tagName') : 通过元素的标签名 $('tagName tagName') : 通过元素的标签名,eg: $('ul li ...

  3. pythonprint字节按照16进制输出_对python以16进制打印字节数组的方法详解

    对python以16进制打印字节数组的方法详解 一.问题描述 如果直接用print打印bytes的话,有时候会直接显示ascii对应的字符,看起来很蛋疼. 二.运行效果 上面一行是直接用print打印 ...

  4. 边信息(即对应的两个数组值)_Python 数据分析 NumPy 模块迭代数组nditer方法详解...

    考虑到实际应用场景中,数组往往不止一个维度,因此遍历数组中所有元素,使用while和for循环写起来很麻烦,本文将介绍NumPy自带的数组遍历方法nditer. 迭代器对象 nditer 在numpy ...

  5. php 二维数组根据键值合并二维数组_php数组实现根据某个键值将相同键值合并生成新二维数组的方法详解...

    这篇文章主要介绍了php数组实现根据某个键值将相同键值合并生成新二维数组的方法,涉及php数组的遍历.赋值相关运算技巧,需要的朋友可以参考下 本文实例讲述了php数组实现根据某个键值将相同键值合并生成 ...

  6. JS进阶篇--JS数组reduce()方法详解及高级技巧

    基本概念 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被 ...

  7. java封装数组_Java封装数组之动态数组实现方法详解

    本文实例讲述了Java封装数组之动态数组实现方法.分享给大家供大家参考,具体如下: 前言:在此之前,我们封装的数组属于静态数组,也即数组空间固定长度,对于固定长度的数组当元素超过容量时会报数组空间不足 ...

  8. JS进阶篇--JS数组reduce()方法详解及高级技巧 1

    基本概念 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被 ...

  9. linux c 数组初始化,C++数组初始化方法详解

    有时在程序中设置变量值比输入变量值更合适.但是,为数组的各个元素编写单独的赋值语句可能意味着大量的输入,对于大型数组而言尤其如此. 例如,来看一个程序: #include #include using ...

最新文章

  1. mysql数据库管理系统的配置文件是_MySQL学习笔记_1_MySQL数据库管理系统概述
  2. 判断一个点是否在RotatedRect中
  3. 如何玩转跨库Join?跨数据库实例查询应用实践
  4. 高效、易用、功能强大的 api 管理平台(内附彩蛋)
  5. 如何读懂UWA性能报告?—NGUI篇
  6. java byte char io流_吃透Java IO:字节流、字符流、缓冲流
  7. 微软携手红帽,共筑开源新未来
  8. 【渝粤教育】国家开放大学2018年秋季 2726T畜禽生产概论 参考试题
  9. 浅谈SDN中的OverLay与UnderLay技术
  10. 24 反转链表(第3章 高质量的代码-代码的鲁棒性)
  11. linux的硬件运行环境,linux下常用的硬件测试软件
  12. 加载字典文件,扫描网站潜在目录
  13. php curl获取404,php使用curl判断网页404(不存在)的方法
  14. Mac与Linux SSH无密登陆(互信)
  15. 服务器cpue5性能,单路的较量 英特尔E3E5处理器性能对比
  16. 上班要了解的一些法律条例
  17. autocad怎么用计算机,职称计算机AutoCAD实用技巧
  18. Lightbox JS 用法
  19. PTA不变初心数(17分)简单答案版
  20. Python 小白学习之:linux 基础和 python 入门

热门文章

  1. java对cookie的操作
  2. chrome dev debug network 的timeline说明
  3. LeetCode - Maximum Depth of Binary Tree
  4. RegularExpressions(4) RegularExpressions 成员(一)
  5. Android UI Button 和GridView 的设计--优化(2)
  6. c#有多少种可能导致写文件失败?
  7. React组件设计之边界划分原则
  8. 最近对Allegro的几个总结
  9. Win7下MATLAB 7.0下载地址和详细安装
  10. 使用 USB 设备安装 Windows 10虚拟机