zoukankan      html  css  js  c++  java
  • lodash源码学习(4)

    继续学习lodash,依然是数组的方法

    “Array” Methods

    _.take(array, [n=1])

     创建一个数组片段包含从数组开始获取的n个元素.

    //take.js
    
    var baseSlice = require('./_baseSlice'),//同Array.slice(见源码学习(3))
        toInteger = require('./toInteger');//转化为整型
    
    /**
     *
     * @param {Array} array 需要查询的数组.
     * @param {number} [n=1] 需要获取的数量.
     * @param- {Object} [guard] 能够作为遍历器被像_.map这样的方法调用.
     * @returns {Array} 返回切好的数组.
     * @example
     *
     * _.take([1, 2, 3]);
     * // => [1]
     *
     * _.take([1, 2, 3], 2);
     * // => [1, 2]
     *
     * _.take([1, 2, 3], 5);
     * // => [1, 2, 3]
     *
     * _.take([1, 2, 3], 0);
     * // => []
     */
    function take(array, n, guard) {
      if (!(array && array.length)) {//如果没有array,或者为空数组,返回空数组
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);//n默认为1
      return baseSlice(array, 0, n < 0 ? 0 : n);//调用baseSlice方法并将结果作为返回值返回
    }
    
    module.exports = take;

    _.takeRight(array, [n=1])

    创建一个数组片段包含从数组末尾获取的n个元素..

    //takeRight.js
    
    var baseSlice = require('./_baseSlice'),//同Array.slice
        toInteger = require('./toInteger');//转化为整型
    
    /**
     *
     * @param {Array} array 需要查询的数组.
     * @param {number} [n=1] 需要获取的元素数量.
     * @param- {Object} [guard] 能够作为遍历器被像_.map这样的方法调用.
     * @returns {Array} 返回切好的数组片段.
     * @example
     *
     * _.takeRight([1, 2, 3]);
     * // => [3]
     *
     * _.takeRight([1, 2, 3], 2);
     * // => [2, 3]
     *
     * _.takeRight([1, 2, 3], 5);
     * // => [1, 2, 3]
     *
     * _.takeRight([1, 2, 3], 0);
     * // => []
     */
    function takeRight(array, n, guard) {
      var length = array == null ? 0 : array.length;
      if (!length) {//如果没有array,或者为空数组,返回空数组
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);//n默认为1
      n = length - n;//从末尾开始算
      return baseSlice(array, n < 0 ? 0 : n, length);//调用baseSlice方法并将结果作为返回值返回
    }
    
    module.exports = takeRight;

    _.takeRightWhile(array, [predicate=_.identity])

     创建一个数组,包含从数组的末尾开始获取元素,直到判断结果为false为止的元素.判断条件接收三个参数(value, index, array)

    //takeRightWhile.js
    
    var baseIteratee = require('./_baseIteratee'),//遍历器封装
        baseWhile = require('./_baseWhile');//从第一个不满足predicate 条件的元素开始截取数组(见源码学习(1))
    
    /**
     *
     * @param {Array} array 需要查询的数组.
     * @param {Function} [predicate=_.identity] 判断条件.
     * @returns {Array} 返回切好的数组片段.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': true },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': false }
     * ];
     *
     * _.takeRightWhile(users, function(o) { return !o.active; });
     * // => objects for ['fred', 'pebbles']
     *
     * // The `_.matches` iteratee shorthand.
     * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
     * // => objects for ['pebbles']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.takeRightWhile(users, ['active', false]);
     * // => objects for ['fred', 'pebbles']
     *
     * // The `_.property` iteratee shorthand.
     * _.takeRightWhile(users, 'active');
     * // => []
     */
    function takeRightWhile(array, predicate) {//如果没有array或者为空数组,返回空数组,否则调用baseWhile方法,并将判断条件封装,使之支持简写,传入第四个参数为true,从右边开始。
      return (array && array.length)
        ? baseWhile(array, baseIteratee(predicate, 3), false, true)
        : [];
    }
    
    module.exports = takeRightWhile;

    _.takeWhile(array, [predicate=_.identity])

    创建一个数组,包含从数组的开始开始获取元素,直到判断结果为false为止的元素.判断条件接收三个参数(value, index, array)

    //takeWhile.js
    
    var baseIteratee = require('./_baseIteratee'),//遍历器封装
        baseWhile = require('./_baseWhile');//从第一个不满足predicate 条件的元素开始截取数组(见源码学习(1))
    
    /**
     *
     * @param {Array} array 需要查询的数组.
     * @param {Function} [predicate=_.identity] 判断条件.
     * @returns {Array} 返回切好的数组片段.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': false },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': true }
     * ];
     *
     * _.takeWhile(users, function(o) { return !o.active; });
     * // => objects for ['barney', 'fred']
     *
     * // The `_.matches` iteratee shorthand.
     * _.takeWhile(users, { 'user': 'barney', 'active': false });
     * // => objects for ['barney']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.takeWhile(users, ['active', false]);
     * // => objects for ['barney', 'fred']
     *
     * // The `_.property` iteratee shorthand.
     * _.takeWhile(users, 'active');
     * // => []
     */
    function takeWhile(array, predicate) {//但是,但是没有传入从右边开始
      return (array && array.length)
        ? baseWhile(array, baseIteratee(predicate, 3))
        : [];//
    }
    
    module.exports = takeWhile;

    _.uniq(array)

    创建一个数组包含原数组中的唯一值.

    _.uniqBy(array, [iteratee=_.identity])

     和_.uniq很像,除了它接收一个遍历器被数组中的每个元素调用。

    _.uniqWith(array, [comparator])

     和_.uniq很像,除了它接收一个比较方法被数组中的每个元素调用,比较方法接收两个参数(arrVal, othVal)

    这三个方法依赖于baseUniq方法,先看源码

    //_baseUniq.js
    
    var SetCache = require('./_SetCache'),//Set缓存数组
        arrayIncludes = require('./_arrayIncludes'),//同Array.includes
        arrayIncludesWith = require('./_arrayIncludesWith'),//同Array.includes除了它接受一个比较方法
        cacheHas = require('./_cacheHas'),//判断缓存中是否含有某个元素
        createSet = require('./_createSet'),//创建Set对象
        setToArray = require('./_setToArray');//将Set对象转为数组
    
    var LARGE_ARRAY_SIZE = 200;//大数组长度(用于数组过大时优化)
    
    /**
     * _.uniqBy的基本实现,不支持遍历器的简写.
     *
     * @private
     * @param {Array} array 需要处理的数组.
     * @param {Function} [iteratee] 遍历器被每个元素调用.
     * @param {Function} [comparator] 比较器被每个元素 调用.
     * @returns {Array} 返回一个没有重复值得数组.
     */
    function baseUniq(array, iteratee, comparator) {
      var index = -1,//数组索引
          includes = arrayIncludes,//是否包含
          length = array.length,//数组长度
          isCommon = true,//是否为常规比较
          result = [],//返回结果
          seen = result;//返回结果的引用(保存被遍历器调用过的值)
    
      if (comparator) {//如果有比较器,不是常规比较,并且比较方法为arrayIncludesWith
        isCommon = false;
        includes = arrayIncludesWith;
      }
      else if (length >= LARGE_ARRAY_SIZE) {//如果数组过长
        var set = iteratee ? null : createSet(array);
        if (set) {//如果没有传遍历器,只用转为Set对象,再转为数组,并将这个数组返回
          return setToArray(set);
        }
        //传了遍历器的情况
    
        isCommon = false;//也不是常规比较
        includes = cacheHas;//比较方法为cacheHas
        seen = new SetCache;//创建一个缓存数组
      }
      else {
        seen = iteratee ? [] : result;//如果有遍历器,seen为空数组,否则为result的引用
      }
      outer:
      //遍历数组
      while (++index < length) {
        var value = array[index],//当前元素
            computed = iteratee ? iteratee(value) : value;//如果有遍历器,对当前元素调用
    
        value = (comparator || value !== 0) ? value : 0;
        if (isCommon && computed === computed) {//常规情况,并且cumputed不为NaN
          var seenIndex = seen.length;//当前结果索引
          //遍历seen
          while (seenIndex--) {
              //如果当前结果中包含computed,跳过
            if (seen[seenIndex] === computed) {
              continue outer;
            }
          }
          if (iteratee) {//如果有遍历器,将computed添加到seen中
            seen.push(computed);
          }
          result.push(value);//将value添加到结果中
        }
        else if (!includes(seen, computed, comparator)) {//非常规比较
          if (seen !== result) {//如果seen为缓存,将computed添加到缓存中
            seen.push(computed);
          }
          result.push(value);//将value添加到结果中
        }
      }
      return result;//返回结果数组
    }
    
    module.exports = baseUniq;

    对应的方法

    uniq

    //uniq.js
    
    var baseUniq = require('./_baseUniq');//baseUniq方法
    
    /**
     *
     * @param {Array} array 需要处理的数组.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * _.uniq([2, 1, 2]);
     * // => [2, 1]
     */
    function uniq(array) {
      return (array && array.length) ? baseUniq(array) : [];//不解释
    }
    
    module.exports = uniq;

    uniqBy

    //uniqBy.js
    
    var baseIteratee = require('./_baseIteratee'),//遍历器封装
        baseUniq = require('./_baseUniq');//baseUniq方法
    
    /**
     *
     *
     * @param {Array} array 需要处理的数组.
     * @param {Function} [iteratee=_.identity] 遍历器,被每个元素调用.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
     * // => [2.1, 1.2]
     *
     * // The `_.property` iteratee shorthand.
     * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 1 }, { 'x': 2 }]
     */
    function uniqBy(array, iteratee) {
      return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : [];//不解释
    }
    
    module.exports = uniqBy;

    uniqWith

    //uniqWith.js
    
    var baseUniq = require('./_baseUniq');//baseUniq方法
    
    /**
     *
     *
     * @param {Array} array 需要处理的数组.
     * @param {Function} [comparator] 比较方法,被每个元素调用.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.uniqWith(objects, _.isEqual);
     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
     */
    function uniqWith(array, comparator) {
      comparator = typeof comparator == 'function' ? comparator : undefined;//比较器不为函数则为空
      return (array && array.length) ? baseUniq(array, undefined, comparator) : [];//不解释
    }
    
    module.exports = uniqWith;

    _.union([arrays])

    创建一个数组,包含给出的所有数组的值的唯一值.

    //union.js
    
    var baseFlatten = require('./_baseFlatten'),//数组扁平化(见源码学习(1))
        baseRest = require('./_baseRest'),//创建具备rest参数的方法
        baseUniq = require('./_baseUniq'),//baseUniq方法
        isArrayLikeObject = require('./isArrayLikeObject');//是否是类似数组的对象
    
    /**
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * _.union([2], [1, 2]);
     * // => [2, 1]
     */
    var union = baseRest(function(arrays) {
        //先将给出的数组扁平化一级之后再调用baseUniq方法,并将结果作为返回值返回。
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
    });
    
    module.exports = union;

    _.unionBy([arrays], [iteratee=_.identity])

    这个方法和_.union很像,除了它接收一个遍历器,被数组中的每个元素调用,遍历器接收一个参数(value)

    //unionBy.js
    
    var baseFlatten = require('./_baseFlatten'),//数组扁平化(见源码学习(1))
        baseIteratee = require('./_baseIteratee'),//遍历器封装
        baseRest = require('./_baseRest'),//创建具备rest参数的方法
        baseUniq = require('./_baseUniq'),//baseUniq方法
        isArrayLikeObject = require('./isArrayLikeObject'),//是否是类似数组的对象
        last = require('./last');//取得最后一个元素
    
    /**
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @param {Function} [iteratee=_.identity] 遍历器,对每个元素调用.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * _.unionBy([2.1], [1.2, 2.3], Math.floor);
     * // => [2.1, 1.2]
     *
     * // The `_.property` iteratee shorthand.
     * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 1 }, { 'x': 2 }]
     */
    var unionBy = baseRest(function(arrays) {//创建可以使用rest参数的方法
      var iteratee = last(arrays);//遍历器为参数的最后一个
      if (isArrayLikeObject(iteratee)) {//如果是一个数组(就是没传),遍历器为undefined
        iteratee = undefined;
      }
      //先将给出的数组扁平化一级之后,并且将遍历器封装,再调用baseUniq方法,并将结果作为返回值返回。
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), baseIteratee(iteratee, 2));
    });
    
    module.exports = unionBy;

    _.unionWith([arrays], [comparator])

    这个方法和_.union很像,除了它接收一个比较方法,被数组中的每个元素调用,比较方法接收两个参数(arrVal, othVal).

    //uniqWith.js
    
    var baseFlatten = require('./_baseFlatten'),//数组扁平化(见源码学习(1))
        baseRest = require('./_baseRest'),//创建具备rest参数的方法
        baseUniq = require('./_baseUniq'),//baseUniq方法
        isArrayLikeObject = require('./isArrayLikeObject'),//是否是类似数组的对象
        last = require('./last');//取得最后一个元素
    
    /**
     * 
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @param {Function} [comparator] 比较方法被每个元素调用.
     * @returns {Array} 返回一个没有重复值得数组.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.unionWith(objects, others, _.isEqual);
     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
     */
    var unionWith = baseRest(function(arrays) {//创建可以使用rest参数的方法
      var comparator = last(arrays);//比较方法为最后一个参数
      comparator = typeof comparator == 'function' ? comparator : undefined;//如果不是函数,比较方法为undefined
      //调用baseUniq方法,并将结果作为返回值返回。
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
    });
    
    module.exports = unionWith;

    _.unzip(array)

    _.zip的逆向,接收一个数组包含组合好的元素,然后创建一个数组重新分组这些元素到展开的状态

    //unzip.js
    
    var arrayFilter = require('./_arrayFilter'),//同Array.filter
        arrayMap = require('./_arrayMap'),//同Array.map
        baseProperty = require('./_baseProperty'),//通过key获取对象的value
        baseTimes = require('./_baseTimes'),//调用方法n次,返回包含每次结果的数组
        isArrayLikeObject = require('./isArrayLikeObject');//是否是一个类似数组的对象
    
    var nativeMax = Math.max;//原生最小值方法
    
    /**
     * 
     *
     * @param {Array} array 收起之后的数组.
     * @returns {Array} 返回展开之后的数组.
     * @example
     *
     * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
     * // => [['a', 1, true], ['b', 2, false]]
     *
     * _.unzip(zipped);
     * // => [['a', 'b'], [1, 2], [true, false]]
     */
    function unzip(array) {
      if (!(array && array.length)) {//如果没有穿array,或者为空数组,返回空数组
        return [];
      }
      var length = 0;
      array = arrayFilter(array, function(group) {//返回array中,所有是数组的元素,并且取得length为最大的数组的长度
        if (isArrayLikeObject(group)) {
          length = nativeMax(group.length, length);
          return true;
        }
      });
      return baseTimes(length, function(index) {//调用length次方法,每次再调用map获得array中每个元素对应index位置的值得数组,然后将包含这些这些数组的数组返回。
        return arrayMap(array, baseProperty(index));
      });
    }
    
    module.exports = unzip;

    _.unzipWith(array, [iteratee=_.identity])

    这个方法和_.unzip很像,除了它接收一个遍历器决定怎么结合这些重组的元素,遍历器接收一个rest参数,表示每个分组中对应元素(...group)

    //unzipWith.js
    
    
    var apply = require('./_apply'),//同Function.apply
        arrayMap = require('./_arrayMap'),//同Array.map
        unzip = require('./unzip');//unzip方法
    
    /**
     * 
     *
     * @param {Array} array 收起之后的数组.
     * @param {Function} [iteratee=_.identity] 遍历器,决定怎么结合这些元素
     * @returns {Array} 返回展开之后的数组.
     * @example
     *
     * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
     * // => [[1, 10, 100], [2, 20, 200]]
     *
     * _.unzipWith(zipped, _.add);
     * // => [3, 30, 300]
     */
    function unzipWith(array, iteratee) {
      if (!(array && array.length)) {//如果没有array或者为空数组,返回空数组
        return [];
      }
      var result = unzip(array);//调用unzip方法执行反压缩
      if (iteratee == null) {//如果没有传入便利器返回result
        return result;
      }
      return arrayMap(result, function(group) {//对结果进行遍历,每次调用iteratee传入每个group的所有元素,然后将处理后的结果作为每个分组的元素。
        return apply(iteratee, undefined, group);
      });
    }
    
    module.exports = unzipWith;

    _.without(array, [values])

    创建一个数组排除所有给定的值

    //widthout.js
    
    var baseDifference = require('./_baseDifference'),//取得数组中不包含过滤数组的元素(见源码学习(1))
        baseRest = require('./_baseRest'),//创建具备rest参数的数组
        isArrayLikeObject = require('./isArrayLikeObject');//是否是类似数组的对象
    
    /**
     * 
     *
     * @param {Array} array 需要处理的数组.
     * @param {...*} [values] 需要排除的值.
     * @returns {Array} 返回过滤后的数组.
     * @example
     *
     * _.without([2, 1, 2, 3], 1, 2);
     * // => [3]
     */
    var without = baseRest(function(array, values) {//创建具备rest参数的数组
        //如果是类似数组,调用baseDifference并将结果作为返回值返回,否则返回空数组
      return isArrayLikeObject(array)
        ? baseDifference(array, values)
        : [];
    });
    
    module.exports = without;

    _.xor([arrays])

     创建一个唯一值得数组,包含给定所有数组中symmetric difference的集合(对差等分,{1,2,3}△{2,3,4} => {1,4})

    _.xorBy([arrays], [iteratee=_.identity])

    这个方法和_.xor很像,除了它接收一个遍历器对每个元素调用,生成比较标准,遍历器接收一个参数(value)

    _.xorWith([arrays], [comparator])

     这个方法和_.xor很像,除了它接收一个比较器对每个元素调用,生成比较标准,比较器接收两个参数(arrVal,othVal)

    这三个方法依赖于baseXor方法,先看源码

    //_baseXor.js
    
    var baseDifference = require('./_baseDifference'),//取得数组中不包含过滤数组的元素(见源码学习(1))
        baseFlatten = require('./_baseFlatten'),//数组扁平化(见源码学习(1))
        baseUniq = require('./_baseUniq');//得到数组中唯一值
    
    /**
     * _.xor的基本实现,不支持遍历器的简写
     *
     * @private
     * @param {Array} arrays 需要处理的数组.
     * @param {Function} [iteratee] 遍历器被每个元素调用.
     * @param {Function} [comparator] 比较器被每个元素调用.
     * @returns {Array} 返回一个新的数组.
     */
    function baseXor(arrays, iteratee, comparator) {
      var length = arrays.length;//数组长度
      if (length < 2) {//如果数组中元素个数小于2
        return length ? baseUniq(arrays[0]) : [];//如果有值得到第一个值得唯一值,否则空数组
      }
      var index = -1,//数组索引
          result = Array(length);//返回结果
    
      //遍历arrays
      while (++index < length) {
        var array = arrays[index],//当前数组
            othIndex = -1;//用于比较的数组的索引
        //遍历用于比较的数组
        while (++othIndex < length) {
          if (othIndex != index) {//如果比较的数组和当前数组不是同一个数组,调用baseDifference方法取得array中不同于当前用于比较的数组的值
            result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
          }
        }
      }
      //调用baseUiq方法,并且将result扁平化一级,然后将得到的唯一值数组返回
      return baseUniq(baseFlatten(result, 1), iteratee, comparator);
    }
    
    module.exports = baseXor;

    对应的方法

    xor

    //xor.js
    
    var arrayFilter = require('./_arrayFilter'),//同Array.filter
        baseRest = require('./_baseRest'),//创建具有rest参数的方法
        baseXor = require('./_baseXor'),//baseXor方法
        isArrayLikeObject = require('./isArrayLikeObject');//是否是类似数组的对象
    
    /**
     *
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @returns {Array} 返回过滤后的数组.
     * @example
     *
     * _.xor([2, 1], [2, 3]);
     * // => [1, 3]
     */
    var xor = baseRest(function(arrays) {//创建具有rest参数的方法
      return baseXor(arrayFilter(arrays, isArrayLikeObject));//调用baseXor并将结果作为返回值返回
    });
    
    module.exports = xor;

    xorBy

    //xorBy.js
    
    var arrayFilter = require('./_arrayFilter'),//同Array.filter
        baseIteratee = require('./_baseIteratee'),//遍历器封装
        baseRest = require('./_baseRest'),//创建具备rest参数的方法
        baseXor = require('./_baseXor'),//baseXor方法
        isArrayLikeObject = require('./isArrayLikeObject'),//是否是一个类似数组的对象
        last = require('./last');//取得数组最后一个元素
    
    /**
     *
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @param {Function} [iteratee=_.identity] 遍历器被每个元素调用.
     * @returns {Array} 返回过滤后的数组.
     * @example
     *
     * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
     * // => [1.2, 3.4]
     *
     * // The `_.property` iteratee shorthand.
     * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 2 }]
     */
    var xorBy = baseRest(function(arrays) {//转化arrays为rest参数
      var iteratee = last(arrays);//遍历器为最后一个参数
      if (isArrayLikeObject(iteratee)) {//最后一个参数为数组,遍历器为undefined
        iteratee = undefined;
      }
      //调用baseXor并且封装遍历器,然后将结果作为返回值返回
      return baseXor(arrayFilter(arrays, isArrayLikeObject), baseIteratee(iteratee, 2));
    });
    
    module.exports = xorBy;

    xorWith

    //xorWith.js
    
    var arrayFilter = require('./_arrayFilter'),//同Array.filter
        baseRest = require('./_baseRest'),//创建具备rest参数的方法
        baseXor = require('./_baseXor'),//baseXor方法
        isArrayLikeObject = require('./isArrayLikeObject'),//是否是一个类似数组的对象
        last = require('./last');//取得数组最后一个元素
    
    /**
     *
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @param {Function} [comparator] 比较器被每个元素调用.
     * @returns {Array} 返回过滤后的数组.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.xorWith(objects, others, _.isEqual);
     * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
     */
    var xorWith = baseRest(function(arrays) {//创建使用rest参数的方法
      var comparator = last(arrays);//比较器为最后一个参数
      comparator = typeof comparator == 'function' ? comparator : undefined;//比较器不是函数则为undefined
      //调用baseXor并且传入比较器,然后将结果作为返回值返回
      return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
    });
    
    module.exports = xorWith;

    _.zip([arrays])

    创建一个数组包含分组之后的元素,第一个元素为所有给出的数组的第一个元素,第二个元素为所有给出的数组的第二个元素,以此类推。

    //zip.js
    
    var baseRest = require('./_baseRest'),//创建具备rest参数的方法
        unzip = require('./unzip');//收起方法
    
    /**
     * 
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @returns {Array} 返回收起之后的数组.
     * @example
     *
     * _.zip(['a', 'b'], [1, 2], [true, false]);
     * // => [['a', 1, true], ['b', 2, false]]
     */
    var zip = baseRest(unzip);//创建unzip的rest参数模式
    
    module.exports = zip;

    _.zipObject([props=[]], [values=[]])

    接收两个数组转化为对象,将第一个数组作为对象的属性,第二个作为对象的值,返回这个对象

    这个方法依赖于baseZipObject和assignValue方法,assignValue方法依赖于baseAssignValue方法

    baseZipObject

    //_baseZipObject.js
    
    /**
     * _.zipObject的基本实现,通过assignFunc进行赋值
     *
     * @param {Array} props 属性名.
     * @param {Array} values 属性值.
     * @param {Function} assignFunc 赋值方法.
     * @returns {Object} 返回新的对象.
     */
    function baseZipObject(props, values, assignFunc) {
      var index = -1,//索引值
          length = props.length,//属性名个数
          valsLength = values.length,//属性值个数
          result = {};//返回结果对象
    
      while (++index < length) {//遍历属性名,如果对应的属性值没有则为undefined
        var value = index < valsLength ? values[index] : undefined;
        assignFunc(result, props[index], value);//使用赋值函数进行赋值
      }
      return result;//返回结果
    }
    
    module.exports = baseZipObject;

    baseAssignValue

    //_baseAssignValue.js
    
    var defineProperty = require('./_defineProperty');//同Object.defineProperty
    
    /**
     * assignValue方法和assignMergeValue的基本实现,不对值进行检查
     *
     * @private
     * @param {Object} object 需要修改的对象.
     * @param {string} key 赋值的key.
     * @param {*} value 赋值的value.
     */
    function baseAssignValue(object, key, value) {
      if (key == '__proto__' && defineProperty) {//如果给__proto__赋值,使用defineProperty赋值
        defineProperty(object, key, {
          'configurable': true,
          'enumerable': true,
          'value': value,
          'writable': true
        });
      } else {//直接赋值
        object[key] = value;
      }
    }
    
    module.exports = baseAssignValue;

    assignValue

    //_assignValue.js
    
    var baseAssignValue = require('./_baseAssignValue'),//baseAssignValue方法
        eq = require('./eq');//判断是否相等
    
    var objectProto = Object.prototype;//对象的原型
    
    var hasOwnProperty = objectProto.hasOwnProperty;//原生hasOwnProperty方法
    
    /**
     * 对对象进行赋值,如果这个值不和本身对象中对象属性的值相同的话
     *
     * @private
     * @param {Object} object 需要修改的对象.
     * @param {string} key 辅助的key.
     * @param {*} value 赋值的value.
     */
    function assignValue(object, key, value) {
      var objValue = object[key];//对象中对应属性的值
      if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
          (value === undefined && !(key in object))) {//如果属性不存在或者和本身的属性不相等,进行赋值操作
        baseAssignValue(object, key, value);
      }
    }
    
    module.exports = assignValue;

    然后再看zipObject就比较清晰了

    //zipObject.js
    
    var assignValue = require('./_assignValue'),//赋值函数
        baseZipObject = require('./_baseZipObject');//baseZipObject方法
    
    /**
     * 接收两个数组转化为对象,将第一个数组作为对象的属性,第二个作为对象的值,返回这个对象
     *
     * @param {Array} [props=[]] 属性名.
     * @param {Array} [values=[]] 属性值.
     * @returns {Object} 返回新的对象.
     * @example
     *
     * _.zipObject(['a', 'b'], [1, 2]);
     * // => { 'a': 1, 'b': 2 }
     */
    function zipObject(props, values) {
      return baseZipObject(props || [], values || [], assignValue);//不解释
    }
    
    module.exports = zipObject;

    _.zipObjectDeep([props=[]], [values=[]])

    这个方法和_.zipObject很像,除了它支持使用属性的路径进行赋值

    //zipObjectDeep.js
    
    var baseSet = require('./_baseSet'),//赋值函数,支持使用属性路径(暂时不分析)
        baseZipObject = require('./_baseZipObject');//baseZipObject方法
    
    /**
     * 
     *
     * @static
     * @memberOf _
     * @since 4.1.0
     * @category Array
     * @param {Array} [props=[]] 属性名.
     * @param {Array} [values=[]] 属性值.
     * @returns {Object} 返回新的对象.
     * @example
     *
     * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
     * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
     */
    function zipObjectDeep(props, values) {
      return baseZipObject(props || [], values || [], baseSet);//不解释
    }
    
    module.exports = zipObjectDeep;

    _.zipWith([arrays], [iteratee=_.identity])

    //zipWith.js
    
    var baseRest = require('./_baseRest'),//创建具备rest参数的方法
        unzipWith = require('./unzipWith');//unzipWith方法。
    
    /**
     * 这个方法和_.zip很像,除了它接收一个遍历器决定怎么结合这些重组的元素,遍历器接收一个rest参数,表示每个分组中对应元素(...group)
     *
     * @param {...Array} [arrays] 需要处理的数组.
     * @param {Function} [iteratee=_.identity] 遍历器,决定怎么结合这些元素
     *  grouped values.
     * @returns {Array} 返回收起之后的数组.
     * @example
     *
     * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
     *   return a + b + c;
     * });
     * // => [111, 222]
     */
    var zipWith = baseRest(function(arrays) {//创建使用rest参数的方法
      var length = arrays.length,//参数长度
          iteratee = length > 1 ? arrays[length - 1] : undefined;//如果参数超过一个,遍历器为最后一个参数
    
      iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;//如果遍历不为function,则为undefined
      return unzipWith(arrays, iteratee);//调用unzipWith方法,并将结果作为返回值返回。
    });
    
    module.exports = zipWith;

    数组部分完结了,这些方法包含了很多对原生方法的重写,以及对数组的的各种遍历计算重组,通过学习这些方法感觉对数组的使用有了更深刻的认识。所以。。。继续加油吧。。。!

  • 相关阅读:
    iOS面试题及答案大总结
    iOS 画音频波形曲线 根据音频数据版
    iPhone-获取网络数据或者路径的文件名
    python语言使用yaml 管理selenium元素
    出现事故后我们怎么复盘分析
    如何提升测试质量,减少漏测
    robotframework环境搭建
    如何做ui自动化---步骤详解
    Jenkins报错Caused: java.io.IOException: Cannot run program "sh" (in directory "D:JenkinsJenkins_homeworkspacejmeter_test"): CreateProcess error=2, 系统找不到指定的文件。
    使用jmeter使用Jenkins发送自定义消息内容
  • 原文地址:https://www.cnblogs.com/wandiao/p/7128228.html
Copyright © 2011-2022 走看看