Array.prototype.reduce在以前用的不多,在位元組跳動面試的時候問到了這個問題,後面就去看了下 MDN,稍微對它理解了些
用法
reduce
方法將陣列從左到右的每個元素依次傳入回撥函式
?是些常用到的地方
統計字串中每個字元出現的次數
方法1 (這種方法是我沒接觸Array.prototype.reduce最常用的方法):
const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
const obj = {}
str.split('').forEach(item => {
obj[item] ? obj[item]++ : obj[item] = 1
})
複製程式碼
方法2 (這個好玩一點點?):
const str = '9kFZTQLbUWOjurz9IKRdeg28rYxULHWDUrIHxCY6tnHleoJ'
const obj = {}
Array.from(str).reduce((accumulator, current) => {
current in accumulator ? accumulator[current]++ : accumulator[current] = 1
return accumulator
}, obj)
複製程式碼
嗯,方法2雖然步驟比方法1複雜些(其實並不複雜吼),但是是不是更好玩些??
篩選陣列中同時滿足多個條件的資料
方法1 (常用):
const arr = [
{
"name": "a1111",
"age": 25
},
{
"name": "a1",
"age": 26
},
{
"name": "a11",
"age": 27
},
{
"name": "a",
"age": 29
},
{
"name": "a11",
"age": 29
},
{
"name": "a11",
"age": 26
},
{
"name": "a111",
"age": 25
},
{
"name": "a11",
"age": 26
},
{
"name": "a1",
"age": 26
},
{
"name": "a",
"age": 26
}
]
arr.filter(item => item.name.length === 3)
.filter(item => item.age > 26)
/*
[
{
"name": "a11",
"age": 27
},
{
"name": "a11",
"age": 29
}
]
*/
複製程式碼
方法2 reduce方法(感謝@zhanggenming的指證,已修改):
const arr = [
{
"name": "a1111",
"age": 25
},
{
"name": "a1",
"age": 26
},
{
"name": "a11",
"age": 27
},
{
"name": "a",
"age": 29
},
{
"name": "a11",
"age": 29
},
{
"name": "a11",
"age": 26
},
{
"name": "a111",
"age": 25
},
{
"name": "a11",
"age": 26
},
{
"name": "a1",
"age": 26
},
{
"name": "a",
"age": 26
}
]
const filter1 = (arr) => arr.filter(item => item.name.length === 3)
const filter2 = (arr) => arr.filter(item => item.age > 26)
const fnArr = [filter1, filter2]
fnArr.reduce((accumulator, fn) => {
accumulator = fn(accumulator)
return accumulator
}, arr)
/*
[
{
"name": "a11",
"age": 27
},
{
"name": "a11",
"age": 29
}
]
*/
複製程式碼
用了這個方法,那我們試試看用for迴圈來實現Array.prortotype.reduce
先看看reduce接收的引數:
arr.reduce(callback[, initialValue])
複製程式碼
reduce方法接收1個callback
的函式作為第一個引數,還有1個可選引數initialValue
。
同時callback
函式有最多4個引數
- accumulator 累加器累加回撥的返回值;它是在最後一次呼叫回撥時返回的累計值。如果提供了initialValue,它的預設值就是initialValue,否則就是陣列的第一個值
- currentValue 當前參與計算的元素
- currentIndex 當前參與計算的元素的陣列下標
- array 當前參與運算的陣列
知道了這些,那我們實現reduce方法就很簡單了
Array.prototype.selfReduce = function() {
const ary = this
const { length } = ary
if (arguments.length === 0) {
throw new TypeError('undefined is not a function')
}
if (typeof arguments[0] !== 'function') {
throw new TypeError(arguments[0] + 'is not a function')
}
if (ary.length === 0 && arguments.length === 1) {
throw new TypeError('Reduce of empty array with no initial value')
}
const callback = arguments[0]
const startIndex = arguments.length >= 2 ? 0 : 1
let value = startIndex === 0 ? arguments[1] : ary[0]
for (let i = startIndex; i < length; i++) {
value = callback(value, ary[i], i, ary)
}
return value
}
複製程式碼
同時,reduce
還有個兄弟?reduceRight
,reduceRight如其名,是將陣列從右到左的將每個元素傳入callback
函式。那實現reduceRight
實現起來也就簡單了。
Array.prototype.selfReduceRight = function () {
const ary = this
const { length } = ary
if (arguments.length === 0) {
throw new TypeError('undefined is not a function')
}
if (typeof arguments[0] !== 'function') {
throw new TypeError(arguments[0] + 'is not a function')
}
if (ary.length === 0 && arguments.length === 1) {
throw new TypeError('Reduce of empty array with no initial value')
}
const startIndex = arguments.length >= 2 ? length - 1 : length - 2
const callback = arguments[0]
let value = startIndex === 0 ? arguments[1] : ary[length - 1]
for (let i = startIndex; i >= 0; i--) {
value = callback(value, ary[i], i, ary)
}
return value
}
複製程式碼