对于前端的循环遍历我们知道有

  • 针对js数组的forEach()、map()、filter()、reduce()方法
  • 针对js对象的for/in语句(for/in也能遍历数组,但不推荐)
  • 针对jq数组/对象的$.each()方法

在语法和参数上他们有什么不同呢?

1.forEach: array.forEach(function(currentValue,index,arr), thisValue)
2.map: array.map(function(currentValue,index,arr), thisValue)
3.filter: array.filter(function(currentValue,index,arr), thisValue)
4.reduce: array.reduce(function(total,currentValue,index,arr), thisValue)
5.$.each: $.each( object/array, function(index,elment) );//jQuery的遍历方法,这里先不多说
6.for/in: for (var key in object) { //... }

  

这些方法都是源于for的封装而来的,先来看看for是怎么循环一个数组的

var arr = [4,3,2,1];

var index = [];
var value = [];
var sum = 0;
for(var i=0;i<arr.length;i++){ index.push(i);
value.push(arr[i])
sum += arr[i]
};
console.log(index); //[0, 1, 2, 3]
console.log(value); // [4,3,2,1]
console.log(sum); //10
//可以看出,i表示的是数组下标,arr[i]是通过下标来去的对应的值

  

forEach、map、filter、reduce方法相同点

**参数
 
 
forEach、map、filter、reduce参数.png

既然他们参数都是一样的,我们以forEach()求和为例,看看各个参数代表着什么

var arr = [4,3,2,1];
var sum = 0;
arr.forEach(function(val,index,arr){
console.log(val); //4
console.log(index); //0
console.log(arr); //[4,3,2,1]
console.log(arr[index]==val); // ==> true
sum+=val
});
console.log(sum); //10

  

从上可得,这几个方法中参数所代表的都是相同的。

关于参数还有一个点没说的是,reduce方法还有个参数,语法如下:
array.reduce(function(total, currentValue, index, arr), initialValue)
其中 currentValue, index, arr意义相同,而total代表计算的初始值, 也是计算结束后的返回值。
其中total, currentValue都是必须的参数。
对于计算一个数组的和,reduce就是很好的方法

var arr = [4,3,2.1,1.1];
var sum = arr.reduce(function(total, val) {
return total + Math.round(val);
});
console.log(sum);//10

  

**迭代时不做修改

这些方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 该方法遍历到它们的那一时刻的值;被删除的元素将不会被访问到。例如:

var words = ["one", "two", "three", "four"];
words.forEach(function(word) {
console.log(word);
if (word === "two") {
words.shift();
}
});
console.log(words);//["two", "three", "four"]

  

**兼容旧环境

这些方法都是ECMA5新增的数组方法,所以ie9以下都不支持,不过,可以从Array原型拓展从而实现以上全部功能,例如forEach方法:

if (typeof Array.prototype.forEach != "function") {
Array.prototype.forEach = function() {
/* 实现 */
};
}

  

下面来看看这几个方法不同的地方

定义:

  1. forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
  2. map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
    map()方法按照原始数组元素顺序依次处理元素
  3. filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。没有到没有符合条件时返回空数组。
  4. reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
  forEach map filter reduce
操作 循环(迭代) 映射 过滤器 汇总
返回值 undefined 返回新数组 返回新数组 返回计算结果total
改变原数组? 看情况
检测空数组? 不检测 不检测 不检测 不检测

下面来看看这几个方法在应用中的不同:
1.对当前数组每个元素乘于100

1.for方法
var b = [1,2,3];
var f = [];
for(var i=0;i<b.length;i++){
f.push(b[i]*100)
};
console.log(f); //[100, 200, 300] 2.forEach方法:
var b = [1,2,3];
var f = []
b.forEach(function(v){
f.push(v*100)
});
console.log(f); //[100, 200, 300]
console.log(b); // [1, 2, 3] 2. forEach方法:
var b = [1,2,3];
b.forEach(function(item,index,arr){
arr[index] = item*100;
});
console.log(b); //[100, 200, 300] 3.map方法:
var b = [1,2,3];
var c = b.map(function(v){ return v*100} )
console.log(c); //[100, 200, 300] 4.for/in语句
var b = [1,2,3];
var f = [];
for(var k in b){ f.push(b[k]*100)
}
console.log(f); //[100, 200, 300]

  

2.对数组的求和

1.for循环
var arr = [1,2,3,4,5];
var sum = 0; //这里sum设置为0或null
for(i=0;i<arr.length;i++){
sum += arr[i];
};
console.log(sum);//15 2.forEach方法
var arr = [1,2,3,4,5];
var sum = 0;
arr.forEach(function(v){
sum += v
})
console.log(sum);//15 3.map方法
//map不适合用来做和,因为他是对每个元素进行处理,再返回每个元素 4.for/in语句
var arr = [1,2,3,4,5];
var sum = 0;
for(var k in arr){
sum += arr[k]
};
console.log(sum); //15

  

3.js如何获取json对象数组中某个属性结合?

var arr = [
{a:1 ,b:2 ,c:3},
{a:4 ,b:5 ,c:6},
{a:7 ,b:8 ,c:9}
];
获取数组arr的a属性集合,有哪些方法? 1.for循环
var res = [];
for(var i=0;i<arr.length;i++){
res.push(arr[i].a)
};
console.log(res); // [1, 4, 7] 2.forEach方法
var res3 = [];
arr.forEach(function(v){
res3.push(v.a);
});
console.log(res3); // [1, 4, 7] 3.map方法
var res2 = arr.map(function(v){
return v.a
});
console.log(res2); // [1, 4, 7] 4.for/in语句
var res4 = [];
for(var k in arr){
res4.push(k);
};
console.log(res4); // ["0", "1", "2"]
//for in 原本是遍历对象的,k为属性的键,所以k在这里为数组的下标。应改成如下
console.log('-----------------------'); var res5 = [];
for(k in arr){
res5.push(arr[k].a)
};
console.log(res5); //[1, 4, 7]

  

4.给json对象数组中的每个对象多加个字段

var users = [
{
lastName: 'Li',
firstName: 'Lei'
},
{
lastName: 'Han',
firstName: 'Meimei'
}
];
给其中每一个对象加一个fullName字段,就把lastName和firstName .for循环
for(var i = ; i < users.length; i++){
var user = users[i];
user.fullName = user.lastName + user.firstName;
}
代码是对的,但却不好(优秀),为什么?原因有2
创建了与主业务无关的for loop
创建了与主业务无关的变量i
用forEach的好处是什么?答案就是解决了上面那2个缺陷,代码如下: .forEach方法
users.forEach(function(user, index, arr){
user.fullName = user.lastName + user.firstName;
}); .map方法
var newUsers = users.map(function(v,i,arr){
v.fullName = v.lastName+v.firstName;
return v
});
//主要如果这里return v.fullName = v.lastName+v.firstName;的话,得到的是["LiLei", "HanMeimei"]
//注意: 此处的map会改变原始数组,因为给v多加了个属性v.fullName

从上我们可以看出,forEach,for/in,map都是封装了for循环,只是在应用的对象上稍有些不同,例如,
forEach主要数组的一些简单遍历
map主要是对数内每个元素的操作
for/in主要是对象键值的一些遍历

应用与细节

forEach方法

forEach的应用只要是数组的简单遍历,这里就不在多做阐述

map方法

map()对数组的每个元素进行一定的操作(映射)后,会返回一个新的数组;是处理服务器返回信息非常有用的函数。

  • 求数组中每个元素的平方↓
只有一个参数来mapping一个数字数组
var res = [1,4,9].map(function(val){
return val*2 //[2,8,18]
});

  

  • 求数组中每个元素的平方根↓
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
//roots的值为[1, 2, 3]
//numbers的值仍为[1, 4, 9]

  

  • 使用map获取json数组中的某个属性集合
var users = [
{name:'zhou' ,email:'zhou@email.com'},
{name:'lin' ,email:'lin@email.com'},
{name:'wu' ,email:'wu@email.com'}
];
var emails = users.map(function(v){
return v.email
});
console.log(emails)
// ["zhou@email.com", "lin@email.com", "wu@email.com"]

  

  • 使用map重新格式化对象数组中的对象↓
var arr= [
{key: 1, value: 10},
{key: 2, value: 20},
{key: 3, value: 30}
];
var reformattedArray = arr.map(function(obj) {
var rObj = {};
rObj[obj.key] = obj.value;
return rObj; //[{1: 10}, {2: 20}, {3: 30}]
});
//注意:
这里是return rObj整个对象,
如果是return rObj[obj.key] = obj.value; 值为[10,20,30]

  

可以看出以上map()的用法都是对集合里的每个元素做对应的实际的操作后,再返回到新的数组里。那如何使只对集合的某些元素做判断呢?返回的是什么,如下面例子:
在数组中取大于3的全部元素

[2, 3, 4, 5].map(function(val, key) {
return val > 3; //[false, false, true, true]
}) [2, 3, 4, 5].map(function(val, key) {
if(val > 3){ return val} //[undefined, undefined, 4, 5]
})

  

上面的结果都不是我们想要的,我们想要的只是纯粹的大于3的集合[4,5],对集合的每个元素进行判断,刷选出符合条件的元素,该怎么做呢?filter就是专为这种处理而生的。

filter方法

filter方法主要是对数组的筛选过滤,返回符合条件的元素,
例如,
------ 对于数组

// 筛选出大于3的数
[2, 3, 4, 5,10].filter(function(val, index) {
return val > 3; //[4,5]
}) // 筛选出能整除5的数
[2, 3, 4, 5,10].filter(function(val, index) {
return val % 5 == 0; //[5,10]
})

  

----- 对于json数组
筛选对象数组中含有‘orange’属性值的对象

var arr = [
{"name":"apple", "count": 2},
{"name":"orange", "count": 5},
{"name":"pear", "count": 3},
{"name":"orange", "count": 16},
]; 1.filter方法
var newArr = arr.filter(function(item){
return item.name === "orange";
});
console.log(newArr);//
[{"name":"orange", "count": 5},
{"name":"orange", "count": 16}] 2.forEach方法
var newArr2 = [];
arr.forEach(function(v){
if(v.name === 'orange'){
newArr2.push(v)
}
});
console.log(newArr2);//
[{"name":"orange", "count": 5},
{"name":"orange", "count": 16}] 4.for循环
var newArr4 = [];
for(var i= 0, l = arr.length; i< l; i++){
if(arr[i].name === "orange" ){
newArr4.push(arr[i]);
}
}
console.log(newArr4); //
[{"name":"orange", "count": 5},
{"name":"orange", "count": 16}] 3.map方法
var newArr3 = arr.map(function(item){
return item.name === "orange";
});
console.log(newArr3);
//[false, true, false, true] Console.log(‘-------------------------------’)
var newArr3 = arr.map(function(v){
if(v.name === 'orange'){ return v }
});
console.log(newArr3)
//
[
undefined,
{"name":"orange", "count": 5},
{"name":"orange", "count": 16},
undefined
]

  

reduce方法

(暂时还不大理解,暂不做解释,哈哈哈哈哈哈哈哈)
请移步到 js中的reduce()函数

上面的分析和举例,同一种功能不同方法的实现,主要是为了让大家理解每个方法的实现的内在原理(for循环),被封装后有什么差异,比如不同参数的值,返回结果,以便在以后的实际应用中能根据业务需求用更简便合适的方法来实现。


根据实际需求做合适的数据处理
有一组成绩,需做一些操作:
1 输出全部考生名字
1 成绩大于60记为及格,否则不及格
2 过滤出成绩大于60的数据
3 计算出总成绩
4 输出:"姓名:xx 成绩:1xx"格式

var grades= [
{name: "优优", grade: 92},
{name: "小渣", grade: 55},
{name: "小优", grade: 82}
] grades.map(v => v.name)
// ["优优", "小渣", "小优"] grades.map(v => v.grade > 60 ? '及格' : '不及格')
// ["及格", "不及格", "及格"] grades.filter(v => v.grade > 60)
// [{name: "优优", grade: 92}, {name: "小优", grade: 82}] grades.reduce((total, v, i, arr) => {
return total + v.grade
},0)
//229 grades.forEach((v, i, arr) => {
v.all = `姓名:${v.name}, 成绩:${v.grade}`
});
console.log(grades)
//[{name: "优优", grade: 92, all: "姓名:优优, 成绩:92"},
//{name: "小渣", grade: 55, all: "姓名:小渣, 成绩:55"},
//{name: "小优", grade: 82, all: "姓名:小优, 成绩:82"}]
//forEach方法会改变原始数组

  

js中数组的循环与遍历forEach,map的更多相关文章

  1. JS中数组与对象的遍历方法实例小结

    一.数组的遍历: 首先定义一个数组 1 arr=['snow','bran','king','nightking']; 1.for循环,需要知道数组的长度; 2.foreach,没有返回值,可以不知道 ...

  2. JS中数组实现(倒序遍历数组,数组连接字符串)

    // =================== 求最大值===================================== <script> var arr = [10,35,765 ...

  3. JS中数组的介绍

    一.数组: 一组数据的集合: 二.JS中数组的特点: 1.数组定义时无需指定数据类型: 2.数组定义时可以无需指定数组长度: 3.数组可以存储任何类型的数据: 4.一般是相同的数据类型: 三.数组的创 ...

  4. js中数组去重的几种方法

    js中数组去重的几种方法         1.遍历数组,一一比较,比较到相同的就删除后面的                 function unique(arr){                 ...

  5. js中数组方法大全

    js数组方法大全 一:前言 我们在学到js中数组的时候,我们会接触到js中数组的一些方法,这些方法对我们来说,可以很遍历的达到我们想要的结果,但是因为方法比较多,有些方法也不常用,可能会过一段时间就会 ...

  6. js中数组去重方法及性能对比

    js中数组的 数组去重 常用的数组去重方法以及效率分析: 首先我们先构建一个数组,主要是用于进行去重实验,我们主要实验的量级为1000,10000,100000,500000.具体的生成数组的方法如下 ...

  7. js中数组扁平化处理

  8. JavaScript -- 时光流逝(二):js中数组的方法

    JavaScript -- 知识点回顾篇(二):js中数组的方法 1. 数组 (1)定义数组,数组赋值 <script type="text/javascript"> ...

  9. php和js中数组的总结

      php中数组的表示方法:array()或者[] js中数组的表示方法:new array()或者[] 一.php中初始化命名数组 在PHP中声明数组的方式主要有两种:一是应用array()函数声明 ...

随机推荐

  1. CAD

    文件另存为——Autocad.doc.SaveAs   一.前言 使用pyautocad编辑好cad图纸后,往往涉及到一个保存的问题,但是官方文档并未提及,所以只能自己来了,测试了好久,终于是找到了保 ...

  2. Game of Credit Cards

    After the fourth season Sherlock and Moriary have realized the whole foolishness of the battle betwe ...

  3. 安装java jdk环境jdk1.8

    1) yum 安装java jdk 1.8 * -y 验证java [root@localhost local]# java -version openjdk version "1.8.0_ ...

  4. 【C语言】多维数组

    C 语言支持多维数组.多维数组声明的一般形式如下: type name[size1][size2]...[sizeN]; 二维数组 多维数组最简单的形式是二维数组.一个二维数组,在本质上,是一个一维数 ...

  5. c语言中void *和NULL

    1.  int *str = NULL; #define NULL    ((void *)0) 空指针实质上是有指向的指针,但它指向的地址是很小的地址,约定俗成为地址0.   2. void *vo ...

  6. python正则匹配次数,贪婪和非贪婪

    贪婪模式  {m,n}表示匹配子串的次数>=m and <=n,再此分为内匹配次数尽可能的多 贪婪模式  {,n}表示 >=0 and <=n 贪婪模式  {m,} 表示> ...

  7. C语言随笔5:函数、函数指针

    函数 C语言中函数参数传递时,将实参的值拷贝到函数参数的存储区中.这种传递参数的方式称为按值传递. 函数不会访问实参本身,访问的是函数存储在栈区的副本,不会改变实参.函数凋用结束,函数在栈区的内容释放 ...

  8. google插件跨域含用户请求WebApi解决的方案

    问题描述: google插件跨域请求WebApi相关解决方案 1.ajax解决含登录用户信息 $.ajax({ url: url, type: "POST", timeout: 6 ...

  9. 浅谈对Jquery+JSON+WebService的使用小结

    https://www.jb51.net/article/36207.htm  更新时间:2013年04月28日 12:19:55   作者:    我要评论   本篇文章介绍了对Jquery+JSO ...

  10. 概率dp lightoj 1342

    题意:有N根木棍,每根木棍都有一个权值 其中有若干根可识别,若干根不可识别的,抽到了可识别的棍子,就不放回,抽到了不可识别的,就要放回 ,问所有棍子都至少被抽过一次后权值和的期望 不可识别的棍子,就相 ...