您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“reduce lodash.reduce實現(xiàn)原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“reduce lodash.reduce實現(xiàn)原理是什么”吧!
實現(xiàn)思路:
判斷是否有初始值,因為有初始值和沒有初始值對回調(diào)函數(shù)(reducer)執(zhí)行的次數(shù)是有影響的。
遍歷數(shù)組
組合參數(shù)傳遞給 reducer 進行執(zhí)行
獲取到第三步返回值的時候,要把返回值存儲起來,在下一次便利的時候作為reducer第一個參數(shù)來替換初始值。
返回最終計算的value值
function reduce(array, reducer, initialValue = null) { let value = initialValue === null ? array[0] : initialValue; // 思路1 let startIndex = initialValue === null ? 1 : 0; // 思路1 for(let i = startIndex; i < array.length; i++) { // 思路 2 const item = array[i] const res = reducer(value, item, i) // 思路3 value = res; // 思路4 } return value; // 思路5 }
測試一下:
console.log(reduce([1,2,3], (a, b) => (a + b), 0)) // 6 console.log(reduce([1,2,3], (a, b) => (a + b))) // 6
看起來是不是挺簡單的,代碼其實還可以更簡潔一點:
function reduce(array, reducer, value = null) { value = value === null ? array[0] : value; for(let i = null ? 1 : 0; i < array.length; i++) { value = reducer(value, array[i], i); } return value; }
lodash中 的 reduce 不僅可以對數(shù)組生效,也可以對普通 object 、類數(shù)組對象生效。
不過也針對數(shù)組其實單獨實現(xiàn)了一個 arrayReduce
函數(shù),不過沒有對外。
來看一下 reduce
和 arrayReduce
源碼
function reduce(collection, iteratee, accumulator) { const func = Array.isArray(collection) ? arrayReduce : baseReduce const initAccum = arguments.length < 3 return func(collection, iteratee, accumulator, initAccum, baseEach) } function arrayReduce(array, iteratee, accumulator, initAccum) { let index = -1 const length = array == null ? 0 : array.length if (initAccum && length) { accumulator = array[++index] } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array) } return accumulator }
看得懂嗎?不理解的話看下面一份代碼,我把非數(shù)組類型的代碼去掉,再調(diào)一下變量命名和新增注釋:
function reduce(array, reducer, value) { const noInitialValue = arguments.length < 3 // 用參數(shù)的數(shù)量來判斷是否有初始值 let index = -1 // 遍歷索引 - 1,因為下面 while 循環(huán)前先加了 1 const length = array == null ? 0 : array.length // 判斷數(shù)組是否存在和緩存數(shù)組長度 // 這個if 語句中做了我上面思路1中初始值的問題和遍歷次數(shù)的問題 if (noInitialValue && length) { // && length 判斷了數(shù)組是否為空 value = array[++index] // 沒有有初始值,則取數(shù)組中第一為,注意 index 變成了0,下面 while 循環(huán)前會先加 1,因此循環(huán)次數(shù)會少一次。 } while (++index < length) { value = reducer(value, array[index], index, array) } return value }
可以看出其實大部分邏輯還是和前面的簡單實現(xiàn)差不多,不過考慮更全一些,有值得借鑒的地方:
參數(shù)判斷邏輯更有力,不管外界傳遞了第三個參數(shù)是啥,都說明有初始值
考慮了數(shù)組不存在或者為空的情況
下面我們再看一下,去除數(shù)組相關的代碼來看看針對其他對象類型怎么處理的。
function reduce(collection, iteratee, accumulator) { const func = baseReduce; const initAccum = arguments.length < 3 return func(collection, iteratee, accumulator, initAccum, baseEach) }
其他類型的都會教給 baseReduce
函數(shù)去處理。
// baseReduce function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { // 使用外部傳遞進來的遍歷方法進行遍歷對象,然后傳遞了一個 callback 給 eachFunc eachFunc(collection, (value, index, collection) => { // 初始值設置, accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection) }) return accumulator }
使用外部傳遞進來的遍歷方法進行遍歷對象,然后傳遞了一個 callback 給 eachFunc,來執(zhí)行 iteratee (也就是前面說的reducer),callback 內(nèi)部的代碼就和前面 for 循環(huán)或者 while 循環(huán)的代碼類似的,就是組合參數(shù)傳遞給 reducer 進行執(zhí)行,不過直接看可能有點不好理解中,了解了原理再來看應該可以理解,注意事項:
initAccum 為 false 時,說明有初始值,直接執(zhí)行 iteratee。
initAccum 為 true,說明沒有初始值,需要添加初始值,因此第一次循環(huán)就是賦值給初始值,然后把 initAccum 設置為false,沒有進行執(zhí)行 iteratee,比沒有初始值少一次執(zhí)行,符合邏輯。
eachFunc
用的是 reduce
中傳遞進來的 baseEach
,內(nèi)部主要就是對對象屬性進行遍歷的操作,然后把屬性值和索引以及對象本身傳遞給 callback,稍微需要注意的就是可能遇到類數(shù)組的對象,為了保證順序,使用類數(shù)組放入索引進行遍歷,而其他對象并不能保證屬性的傳遞順序,可以再看一下baseEach實現(xiàn)的代碼:
function baseEach(collection, iteratee) { if (collection == null) { return collection } // 不是類數(shù)組則使用 baseForOwn 處理 if (!isArrayLike(collection)) { return baseForOwn(collection, iteratee) } const length = collection.length const iterable = Object(collection) // 使用arguments測試了一下,好像沒啥作用 let index = -1 // 遍歷類數(shù)組 while (++index < length) { if (iteratee(iterable[index], index, iterable) === false) { break } } return collection }
不是 isArrayLike
的對象遍歷與本篇文章的內(nèi)容沒有啥關系了,因此就不深入了。
到此,相信大家對“reduce lodash.reduce實現(xiàn)原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。