_.reduceRight(collection, [iteratee=_.identity], [accumulator])
85
_.reduceRight(collection, [iteratee=_.identity], [accumulator])
_.reduceRight与reduce方法类似,遍历集合元素,调用iteratee,返回累加器对象。区别是遍历的顺序是从右往左
参数
collection (Array|Object): 需要遍历的集合
[iteratee=_.identity] (Function): 每一次遍历调用的方法
[accumulator] (*): 累加器初始值
返回值
(*): 返回累加器
例子
var array = [[0, 1], [2, 3], [4, 5]]; _.reduceRight(array, function(flattened, other) { return flattened.concat(other); }, []); // => [4, 5, 2, 3, 0, 1]
源代码:
import arrayReduceRight from './.internal/arrayReduceRight.js' import baseEachRight from './.internal/baseEachRight.js' import baseReduce from './.internal/baseReduce.js' /** * This method is like `reduce` except that it iterates over elements of * `collection` from right to left. * * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @returns {*} Returns the accumulated value. * @see reduce * @example * * const array = [[0, 1], [2, 3], [4, 5]] * * reduceRight(array, (flattened, other) => flattened.concat(other), []) * // => [4, 5, 2, 3, 0, 1] */ //与reduce方法类似,遍历集合元素,调用iteratee,返回累加器对象。区别是遍历的顺序是从右往左 function reduceRight(collection, iteratee, accumulator) { const func = Array.isArray(collection) ? arrayReduceRight : baseReduce //如果collection是数组,就用arrayReduceRight处理,否则用baseReduce处理 const initAccum = arguments.length < 3//标记,是否将集合的第一个元素作为累加器初始值 return func(collection, iteratee, accumulator, initAccum, baseEachRight) //调用对应基础方法处理 } export default reduceRight
arrayReduceRight
/** * A specialized version of `reduceRight` for arrays. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initAccum] Specify using the last element of `array` as * the initial value. * @returns {*} Returns the accumulated value. */ //针对数组类型的reduceRight方法 function arrayReduceRight(array, iteratee, accumulator, initAccum) { let length = array == null ? 0 : array.length//数组长度 if (initAccum && length) {//如果没有传递累加器初始值,就用数组第一个元素作为累加器初始值 accumulator = array[--length] } while (length--) {//遍历数组,每一个元素调用iteratee后的返回值作为下一轮的累加器对象 accumulator = iteratee(accumulator, array[length], length, array) } return accumulator//返回累加器 } export default arrayReduceRight
baseReduce
/** * The base implementation of `reduce` and `reduceRight` which iterates * over `collection` using `eachFunc`. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initAccum Specify using the first or last element of * `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ //reduce基础实现,使用eachFunc方法执行累加的方法 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { eachFunc(collection, (value, index, collection) => { accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection) //如果没有提供累加初始值,就用第一个元素作为初始值 }) return accumulator } export default baseReduce
baseEachRight
import baseForOwnRight from './baseForOwnRight.js' import isArrayLike from '../isArrayLike.js' /** * The base implementation of `forEachRight`. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object} Returns `collection`. */ //forEachRight的基础实现 function baseEachRight(collection, iteratee) { if (collection == null) {//如果collection为空,就直接返回 return collection } if (!isArrayLike(collection)) {//如果collection不是array-like对象,调用baseForOwnRight处理 return baseForOwnRight(collection, iteratee) } const iterable = Object(collection)//array-like对象化 let length = collection.length//循环索引,从右往左 while (length--) {//循环,如果iteratee返回了false,就提前跳出循环 if (iteratee(iterable[length], length, iterable) === false) { break } } return collection } export default baseEachRight
baseForOwnRight
import baseForRight from './baseForRight.js' import keys from '../keys.js' /** * The base implementation of `forOwnRight`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ //forOwnRight基础实现 function baseForOwnRight(object, iteratee) { return object && baseForRight(object, iteratee, keys)//如果object存在调用baseForRight处理 } export default baseForOwnRight
baseForRight
/** * This function is like `baseFor` except that it iterates over properties * in the opposite order. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ //类似baseFor方法,遍历属性从相反的顺序 function baseForRight(object, iteratee, keysFunc) { const iterable = Object(object) const props = keysFunc(object)//键组成的数组 let { length } = props//键数组长度 while (length--) {//循环键数组,从右往左的顺序 const key = props[length]//当前键 if (iteratee(iterable[key], key, iterable) === false) {//调用iteratee,如果返回false,就提前跳出循环 break } } return object } export default baseForRight
keys
import arrayLikeKeys from './.internal/arrayLikeKeys.js' import isArrayLike from './isArrayLike.js' /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @since 0.1.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @see values, valuesIn * @example * * function Foo() { * this.a = 1 * this.b = 2 * } * * Foo.prototype.c = 3 * * keys(new Foo) * // => ['a', 'b'] (iteration order is not guaranteed) * * keys('hi') * // => ['0', '1'] */ //创建一个给定对象的自身可枚举属性组成的数组 function keys(object) { return isArrayLike(object) ? arrayLikeKeys(object) : Object.keys(Object(object)) //如果object是array-like对象,就调用arrayLikeKeys,否则使用原生的Object.keys方法 } export default keys
arrayLikeKeys
import isArguments from '../isArguments.js' import isBuffer from '../isBuffer.js' import isIndex from './isIndex.js' import isTypedArray from '../isTypedArray.js' /** Used to check objects for own properties. */ const hasOwnProperty = Object.prototype.hasOwnProperty /** * Creates an array of the enumerable property names of the array-like `value`. * * @private * @param {*} value The value to query. * @param {boolean} inherited Specify returning inherited property names. * @returns {Array} Returns the array of property names. */ //创建一个给定array-like对象的自身可枚举属性组成的数组 function arrayLikeKeys(value, inherited) { const isArr = Array.isArray(value)//是否是数组 const isArg = !isArr && isArguments(value)//是否是arguments对象 const isBuff = !isArr && !isArg && isBuffer(value)//是否是buffer对象 const isType = !isArr && !isArg && !isBuff && isTypedArray(value)//是否是typedArray const skipIndexes = isArr || isArg || isBuff || isType//这四种类型需要跳过数字索引 const length = value.length//value的长度 const result = new Array(skipIndexes ? length : 0)//结果数组 let index = skipIndexes ? -1 : length//循环索引 while (++index < length) { result[index] = `${index}` } for (const key in value) {//循环属性,将非index属性和非特殊属性push进结果数组 if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && ( // Safari 9 has enumerable `arguments.length` in strict mode. (key == 'length' || // Node.js 0.10 has enumerable non-index properties on buffers. (isBuff && (key == 'offset' || key == 'parent')) || // PhantomJS 2 has enumerable non-index properties on typed arrays. (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || // Skip index properties. isIndex(key, length)) ))) { result.push(key) } } return result } export default arrayLikeKeys

浙公网安备 33010602011771号