對於前端的循環遍歷咱們知道有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方法會改變原始數組