Lodash源码解析一difference

139 阅读1分钟

_.difference

文档注释

image.png

image.png

关联函数

image.png

源码解析

 // 调用示例
difference([1,2,3,4],[2,3]) // ====> [1,4]

// 具体源码
var difference = baseRest(function(array, values) {
	/* 
        baseRest可以理解对传值做了层处理,打印array是原值,values是在外面又套了层数组
        比如传值values:[1,2]  ===> 转化为[[1,2]]
    */
      return isArrayLikeObject(array)  // 这一步好理解,判断是否是数组结构
        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
        : [];
    });


function baseFlatten(array, depth, predicate, isStrict, result) {
      var index = -1,
          length = array.length;

		predicate || (predicate = isFlattenable);
		result || (result = []);

      while (++index < length) { // 因为数据是[[1,2]]===> length = 1, 因此只循环一次就停止
        var value = array[index];
        if (depth > 0 && predicate(value)) {
          if (depth > 1) {
            // Recursively flatten arrays (susceptible to call stack limits).
            baseFlatten(value, depth - 1, predicate, isStrict, result);
          } else {
            /* 
             * 进了到这一步,核心代码,可以理解为拷贝了一份到新的数据到result
             * result: 空数组 [] 
             * value:  为[2,3]
             */ 
            arrayPush(result, value);

            // function arrayPush(array= [], values = [2,3]) {
            //   var index = -1, 
            //       length = values.length,
            //       offset = array.length;
          
            //   while (++index < length) {
            //     array[offset + index] = values[index];
            //   }
            //   return array;
            // }
          }
        } else if (!isStrict) {
          result[result.length] = value;
        }
      }
      return result;
    }

function baseDifference(array=[1,2,3,4], values = [2,3], iteratee=null, comparator=null) {
      var index = -1,
          includes = arrayIncludes,
          isCommon = true,
          length = array.length, // 4
          result = [],
          valuesLength = values.length; // 2
          console.log(arrayIncludes)

      if (!length) {
        return result;
      }
      if (iteratee) {
        values = arrayMap(values, baseUnary(iteratee));
      }
      if (comparator) {
        includes = arrayIncludesWith;
        isCommon = false;
      }
      else if (values.length >= LARGE_ARRAY_SIZE) {
        includes = cacheHas;
        isCommon = false;
        values = new SetCache(values);
      }
      /*
       *核心代码开始
      */
      outer:  // java用的一个方法,内部循环可以控制外部的循环
      while (++index < length) {
        var value = array[index],
            computed = iteratee == null ? value : iteratee(value);

        value = (comparator || value !== 0) ? value : 0;
        if (isCommon && computed === computed) {
          var valuesIndex = valuesLength;
          while (valuesIndex--) {
            if (values[valuesIndex] === computed) {
              continue outer; // 跳到外部的循环,此处下部的push不在继续
            }
          }
          result.push(value);
        }
        else if (!includes(values, computed, comparator)) {
          result.push(value);
        }
      }
      return result;
         /*
       *核心代码结束
      */
    }

核心代码说明

看似方法很多,其他方法可理解为检验和处理数据,核心代码函数在baseDifference里面,通过控制外层循环,判断是不是需要把值push到新的数组中,找到相同的值跳出push操作,跳到在最外层重新循环