js中數組的循環與遍歷forEach,map

對於前端的循環遍歷咱們知道有javascript

  • 針對js數組的forEach()、map()、filter()、reduce()方法
  • 針對js對象的for/in語句(for/in也能遍歷數組,但不推薦)
  • 針對jq數組/對象的$.each()方法

在語法和參數上他們有什麼不一樣呢?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、map、filter、reduce方法相同點

**參數
 
 
forEach、map、filter、reduce參數.png


既然他們參數都是同樣的,咱們以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

定義:函數

  1. forEach() 方法用於調用數組的每一個元素,並將元素傳遞給回調函數。
  2. map() 方法返回一個新數組,數組中的元素爲原始數組元素調用函數處理後的值。
    map()方法按照原始數組元素順序依次處理元素
  3. filter() 方法建立一個新的數組,新數組中的元素是經過檢查指定數組中符合條件的全部元素。沒有到沒有符合條件時返回空數組。
  4. reduce() 方法接收一個函數做爲累加器,數組中的每一個值(從左到右)開始縮減,最終計算爲一個值
  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方法

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方法會改變原始數組
相關文章
相關標籤/搜索