JavaScript中數組排序深度講解

ES5和ES6數組遍歷方法詳解

在ES5中經常使用的10種數組遍歷方法:

一、原始的for循環語句
二、Array.prototype.forEach數組對象內置方法
三、Array.prototype.map數組對象內置方法
四、Array.prototype.filter數組對象內置方法
五、Array.prototype.reduce數組對象內置方法
六、Array.prototype.some數組對象內置方法
七、Array.prototype.every數組對象內置方法
八、Array.prototype.indexOf數組對象內置方法
九、Array.prototype.lastIndexOf數組對象內置方法
十、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:性能改良版this

var a = [1,2,3];
for(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 的值,會發現實際上是-1prototype

數組內置方法Array.prototype.forEach

Examplecode

var a = [1,2,3];
a.forEach(function(value,key,arr){
  console.log(value)    // 結果依次爲1,2,3
  console.log(key)      // 結尾依次爲0,1,2
  console.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,3
    console.log(key)      // 結尾依次爲0,1,2
    console.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,3
    console.log(key)      // 結尾依次爲0,1,2
    console.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,3
    console.log(key)      // 結尾依次爲0,1,2
    console.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,3
    console.log(key)      // 結尾依次爲0,1,2
    console.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,3
    console.log(key)      // 結尾依次爲0,1,2
    console.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,3
  console.log(value);   // 結果依次爲1,2,3
  console.log(key);     // 結果依次爲0,1,2
  console.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,3
  console.log(value);   // 結果依次爲1,2,3
  console.log(key);     // 結果依次爲0,1,2
  console.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,2
  console.log(key);     // 結果依次爲0,1
  console.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,2
  console.log(key);     // 結果依次爲0,1
  console.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,2
  console.log(key);     // 結果依次爲0,1
  console.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,2
  console.log(key);     // 結果依次爲0,1
  console.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語句不一樣的是它不能夠循環對象,只能循環數組。

相關文章
相關標籤/搜索