_.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

 

posted @ 2018-11-09 13:12  hahazexia  阅读(197)  评论(0)    收藏  举报