对于前端的循环遍历咱们知道有javascript
在语法和参数上他们有什么不一样呢?css
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()求和为例,看看各个参数表明着什么java
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就是很好的方法json
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() { /* 实现 */ }; }
下面来看看这几个方法不一样的地方app
定义:函数
forEach | map | filter | reduce | |
---|---|---|---|---|
操做 | 循环(迭代) | 映射 | 过滤器 | 汇总 |
返回值 | undefined | 返回新数组 | 返回新数组 | 返回计算结果total |
改变原数组? | 看状况 | 否 | 否 | 否 |
检测空数组? | 不检测 | 不检测 | 不检测 | 不检测 |
下面来看看这几个方法在应用中的不一样:
1.对当前数组每一个元素乘于100oop
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 1.for循环 for(var i = 0; i < users.length; i++){ var user = users[i]; user.fullName = user.lastName + user.firstName; } 代码是对的,但却很差(优秀),为何?缘由有2 建立了与主业务无关的for loop 建立了与主业务无关的变量i 用forEach的好处是什么?答案就是解决了上面那2个缺陷,代码以下: 2.forEach方法 users.forEach(function(user, index, arr){ user.fullName = user.lastName + user.firstName; }); 3.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的应用只要是数组的简单遍历,这里就不在多作阐述
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]
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"]
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方法主要是对数组的筛选过滤,返回符合条件的元素,
例如,
------ 对于数组
// 筛选出大于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 ]
(暂时还不大理解,暂不作解释,哈哈哈哈哈哈哈哈)
请移步到 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方法会改变原始数组