Array.reduce()方法的使用
起因是學習異步函數的串行與並行寫法時,發現reduce方法可以簡化寫法,然後看到一篇博客裏面這樣一段代碼:
var array = [1, [2, [3, 4], 5], 6]; function flatten(array) { return array.reduce(function (arr, item) { return (Object.prototype.toString.call(item) === ‘[object Array]‘ ? Array.prototype.push.apply(arr, flatten(item)) : arr.push(item) , arr); }, []); } console.log(flatten(array));
發現好多不理解的地方,花費些許時間終於弄懂了:
- reduce(fn,initValue)接收2個參數。第一個是叠代器函數,函數的作用是對數組中從左到右的每一個元素進行處理。函數有4個參數,分別是accumulator、currentValue、currentIndex、array。
accumulator 累加器,即函數上一次調用的返回值。第一次的時候為 initialValue || arr[0]
currentValue 數組中函數正在處理的的值。第一次的時候initialValue || arr[1]
currentIndex 數組中函數正在處理的的索引
array 函數調用的數組
initValue reduce 的第二個可選參數,累加器的初始值。沒有時,累加器第一次的值為currentValue;
2. return (a,b) 這裏其實就是逗號運算符了。先計算左邊,再計算右邊,最後返回右邊的值。比如
var n = (1,2,3,4); console.log(n); //4
3. 然後reduce的第一個參數的這個函數一定要每次都有返回值;
4. Array.prototype.push.apply(arr1,arr2)為什麽可以把2個數組concat()起來。
我覺得我應該能想的出來的,以前看過但沒怎麽用,印象不深刻,所以沒記起來。
這個從 call 、apply、bind 說起。
fn.call() 第一個參數,傳入調用的對象,第二個以後的參數為fn的參數,一一對應;
fn.apply() 同上,第二個參數變為數組,數組中的元素與fn的參數一一對應;
fn.bind() 同 apply ,不過 call apply 直接就執行了, bind 是生成了一個新函數,在需要的時候執行。
這樣就出來了, Array.prototype.push.apply(arr1,arr2) 將 arr2 中的每一個元素當成參數 push 到 arr1 中去了,而不是arr1.push(arr2)。
所以上述的意思就是,第一次叠代時 accumulator 的值為[],然後遞歸調用flatten,每次都返回accumulator
此外 apply 還有很多巧妙的用處,比如數組找最大值Math.max.apply(Math,arr);
偽數組的轉換Array.prototype.slice.apply(arguments)
上文說過fn.apply()接收2個參數,一個是context,一個是數組作為參數。此時只傳了一個上下文環境(arguments是偽數組,本身沒有slice方法,所以借用數組原型上的方法),而slice本身是沒有傳參數的。不傳參數默認為slice(0),即 Array.prototype.slice.apply(arguments,[0])所以就將整個數組復制一份返回出來了。
關於promise
reduce 可以使 promise 的串行.then()寫法變得簡單;
// promise生成函數 function log(n, delay, param) { return function () { return new Promise((resolve, reject) => { setTimeout(() => { console.log(n); resolve(param); }, delay); }) } } /**異步函數的串行1 * 這是正常的promise鏈式調用,每個then裏面都返回一個promise; * 上一個執行完成,下一個才會執行 */ Promise.resolve() .then(log(1,300)) .then(log(2,0)) .then(log(3,500)) .then(log(4,100));
上面的代碼按順序打印出1、2、3、4。
如果想讓1、2、3、4全部執行完畢後再執行某個函數,則可以用Promise.all(arr)
方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例。具體示例如下:
//異步函數的並行寫法 Promise.all([ log(1, 300, "aa")(), log(2, 0, "bb")(), log(3, 1500, "cc")(), log(4, 100, "dd")() ]).then((result) => { console.log(‘finished!‘) console.log(result); }); //2 //4 //1 //3 //finished! //[ ‘aa‘, ‘bb‘, ‘cc‘, ‘dd‘ ]
如果想讓串行的寫法和這種並行的寫法差不多的話,可以用到reduce()
函數
//異步函數的串行2 //reduce中傳入Promise.resolve()作為累加器的初始值 //第一次時Promise.resolve().then(fn)傳入一個函數log(1, 300),函數運行後返回promis實例 //這個實例作為第二次的累加器的值,然後調用它的then()方法,並傳入數組的第二項... [log(1, 300),log(2, 0),log(3, 500),log(4, 100)].reduce((accumulator, value) => { return accumulator.then(value) },Promise.resolve());
結果和上面的串行1一樣,按順序打印出來1、2、3、4
原文鏈接:https://blog.csdn.net/q1325545052/article/details/78851786
參考鏈接:https://blog.csdn.net/zhendong9860/article/details/74908062
Array.reduce()方法的使用