陣列的高階應用含ES6 for of 用法
阿新 • • 發佈:2018-12-10
// 在ES5中常用的10種陣列遍歷方法:
// 1、 原始的for迴圈語句
// 2、 Array.prototype.forEach陣列物件內建方法
// 3、 Array.prototype.map陣列物件內建方法
// 4、 Array.prototype.filter陣列物件內建方法
// 5、 Array.prototype.reduce陣列物件內建方法
// 6、 Array.prototype.some陣列物件內建方法
// 7、 Array.prototype.every陣列物件內建方法
// 8、 Array.prototype.indexOf陣列物件內建方法
// 9、 Array.prototype.lastIndexOf陣列物件內建方法
// 10、 for...in迴圈語句
// ES6中新增加了一種: // 1.for...of迴圈語句 // ES5三種陣列迴圈示例如下: // 示例1------------------------------>>>>>>>>>>>> // 原始for迴圈語句 Example1 // var a = [1,2,3]; // for (var i=0;i<a.length;i++){ // console.log(a[i]); // } //程式碼解讀:原始for迴圈的優點在於大家都比較熟悉,容易理解,劣勢是寫起來比較繁瑣, // 需要定義額外更多的變數,所以一下是針對於原始for迴圈的改良的兩種寫法: // Example1 寫法改良版 // var a = [1,2,3]; // for (var i = a.length; i--;) { // console.log(a[i]); //結果依次為3,2,1 // } // Example1 效能改良版 // var a = [1, 2, 3]; // for (var i = 0, len = a.length; i < len; i++) { // console.log(a[i]); // } // 示例2------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.forEach // var a = [1, 2, 3]; // a.forEach(function (value, index) { // console.log(value); // 結果依次為1,2,3 // }); // a.forEach(function (value, index) { // console.log(index); // 結尾依次為0,1,2 // }); // 程式碼解讀:forEach方法最大的好處就是便於使用,而且不用定義額外的引數變數, // 但是從效率以及效能角度來說它是劣於原始for迴圈的,而且也不能強制return結束迴圈,原因如下: // **forEach迴圈**一看就是通過**回撥函式**來提供引數的,而回調函式在JS中是**閉包**的一種, // 閉包的作用是用來生成**私有作用域**的,所以,每一個回撥函式都是一個**獨立的作用域**, // 都擁有自己獨立的儲存空間,互不影響,而且內部變數還不及時釋放,這也就是為什麼在能不用閉包的情況下就不要用閉包的原因, // 而在閉包中return的話,也只是在當前回撥函式中返回了,可是forEach中的其他的回撥函式(閉包)仍然存在, // 所以,導致return是沒辦法結束迴圈的。下面寫一個forEach迴圈實現例子供大家參考理解: // 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); // console.log(key); // console.log(arr); // }) // 示例3------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.map // var a = [1, 2, 3]; // var b = a.map(function (value) { // console.log(value); // 結果依次為1,2,3 // return value * 2; // }); // console.log(b); //結果為[ 2, 4, 6 ]; // 程式碼解讀: map和forEach不同, 在forEach中return語句是沒有任何效果的, // 而map則可以改變當前迴圈的值, 並且最終會返回一個新的被改變過值之後的陣列( map如果不用return就和forEach一樣了), // 由於這個特性, map一般用來處理需要修改某一個數組的值。 map和forEach在其他的方面都是一樣的, // 也不能return結束迴圈等特性, 下面寫一個map迴圈實現的例子供大家參考理解: // 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); // console.log(key); // console.log(arr); // }); // 示例4------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.filter // var a=[1,2,3]; // var b = a.filter(function(value,key,arr){ // if(value > 2){ // return true; // } // }); // console.log(b); // 程式碼解讀:filter和map不同,map目的是為了改變值,而filter目的是為了去掉不要的值, // 在迴圈的時候如果返回的是false那麼就表示本次迴圈的不新增該值,返回true則相反是表示要新增到新建的陣列中, // 下面寫一個filter迴圈實現例子供大家參考: // 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 ] // 示例5------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.reduce // 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迴圈實現例子供大家參考: // 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 // 示例6------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.some // var a=[1,2,3]; // var b = a.some(function(value){ // return value ==2; // }); // console.log(b); // 程式碼解讀:some的不同之處在它返回的布林值,它的作用有點像filter,不過它的目的不是為了篩選返回陣列, // 而是為了篩選該陣列是否有滿足你要的值,而且找到符合條件的值返回了一次true之後就不會再繼續執行了,下面寫一個some迴圈實現例子供大家參考: // 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 // 示例7------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.every // 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迴圈實現例子供大家參考: // 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 // 示例8------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.indexOf // var a = [1, 2, 3]; // var b = a.indexOf(1); // console.log(b); // 碼解讀:對於indexOf方法來說,在陣列迴圈過程中會和傳入的引數比對,如果是比對成功,那麼終止迴圈, // 返回對比成功的下標,下面寫一個indexOf迴圈實現例子供大家參考: // 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 // 示例9------------------------------>>>>>>>>>>>> // 陣列內建方法Array.prototype.lastIndexOf // 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迴圈實現例子供大家參考: // 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方法相當於你告訴它你要找什麼值, 找到之後立馬返回給你它的門牌號。 // 示例10------------------------------>>>>>>>>>>>> // var a=[1,2,3]; // for(var k in a){ // console.log(k); // } // var b ={ // 0:1, // 1:2, // 2:3, // }; // for(var k in b ){ // console.log(k); // } // 程式碼解讀:從結果得知,for...in遍歷陣列的時候是遍歷陣列的下標值,而在遍歷物件的時候遍歷的是key值, // 所以猜想,陣列在JS中,本質上也是一個以鍵值對形式存在的物件,而為了證明這點,我們做如下一個例子的實驗: // var a = []; // a['b'] = 2; // a['c'] = 3; // console.log(a); // console.log(a[0]); // 我們發現數組的下標不在對應相應位置的值了,由此可以證明在JS中陣列其實本質上就是一個以下標為key值的物件。 // 當然對於for...in迴圈語句本身而言, 它是一個淺度遍歷物件的迴圈語句, 值遍歷第一層節點( 當然物件中設定不可列舉的屬性的除外)。 // var a={ // b:{ // c:2, // }, // d:{ // e:3, // } // }; // for (var k in a){ // console.log(k); // } // ES6迴圈for...of語句 // var a = [1,2,3]; // for (var value of a){ // console.log(value); // } // 程式碼解讀:for...of語句看著有點像for...in語句,但是和for...in語句不同的是它不可以迴圈物件,只能迴圈陣列。