JavaScript實用庫:Lodash源碼數組函數解析(二) difference、baseDifference、isArrayLikeObject、isArrayLike、baseRest

本章內容主要是:difference、baseDifference、isArrayLikeObject、isArrayLike、baseRest

在這裏插入圖片描述

Lodash是一個非常好用方便的JavaScript的工具庫,使得我們對數據處理能夠更加得心應手

接下來我要對Lodash的源碼進行剖析學習
每天幾個小方法,跟着我一起來學lodash吧

  


1、_.difference(array, [values])

根據中文文檔介紹,該函數就是可以將 array中的排除掉[values]中的元素,這是我個人的話語解釋,我們來看中文文檔解釋
在這裏插入圖片描述

以下是例子:
例子中我們輸入了兩個數組,第一個數組保持了存在的唯一值
在這裏插入圖片描述
接下來我們看源碼:

/**
 * Creates an array of `array` values not included in the other given arrays
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons. The order and references of result values are
 * determined by the first array.
 *
 * **Note:** Unlike `_.pullAll`, this method returns a new array.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to inspect.
 * @param {...Array} [values] The values to exclude.
 * @returns {Array} Returns the new array of filtered values.
 * @see _.without, _.xor
 * @example
 *
 * _.difference([2, 1], [2, 3]);
 * // => [1]
 */
var difference = baseRest(function(array, values) {
  return isArrayLikeObject(array)
    ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
    : [];
});

module.exports = difference;

  一上來我們就可以看到還使用了其他的很多方法,就像我們昨天的老朋友:扁平化數組 baseFlatten
  這裏的話 baseFlatten我就不過多介紹了

  • baseDifference
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/**
 * The base implementation of methods like `_.difference` without support
 * for excluding multiple arrays or iteratee shorthands.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {Array} values The values to exclude.
 * @param {Function} [iteratee] The iteratee invoked per element.
 * @param {Function} [comparator] The comparator invoked per element.
 * @returns {Array} Returns the new array of filtered values.
 */
function baseDifference(array, values, iteratee, comparator) {
  var index = -1,
      includes = arrayIncludes,
      isCommon = true,
      length = array.length,
      result = [],
      valuesLength = values.length;

  // 判斷如果數組的長度是 0,則返回空數組
  if (!length) {
    return result;
  }
  if (iteratee) {
    values = arrayMap(values, baseUnary(iteratee));
  }
  if (comparator) {
    includes = arrayIncludesWith;
    isCommon = false;
  }

  // 當數組的長度大於 200 時執行,這是前面給出的常量。
  else if (values.length >= LARGE_ARRAY_SIZE) {
    includes = cacheHas;
    isCommon = false;
    values = new SetCache(values);
  }

  // 標籤語法
  outer:

  while (++index < length) {
    var value = array[index],
        // 當 iteratee == null 時返回 value,否則返回 iteratee(value)
        computed = iteratee == null ? value : iteratee(value);

    // 當 comparator 存在或者 value !==0 時,value = value
    value = (comparator || value !== 0) ? value : 0;
    if (isCommon && computed === computed) {
      var valuesIndex = valuesLength;
      while (valuesIndex--) {
        if (values[valuesIndex] === computed) {
        // 如果 values 中有值等於 computed,就退出到最外層的循環,這就是標籤語法的作用
          continue outer;
        }
      }
      result.push(value);
    }
    else if (!includes(values, computed, comparator)) {
      result.push(value);
    }
  }
  return result;
}

module.exports = baseDifference;

  比如 baseDifference([1, 2], [2, 3, 4]) 這裏 array = [1, 2] , values = [2, 3, 4]
  初始值 result = [], valuesLength = 3
  for 遍歷,第一個值 value = 1, computed = 1, valuesIndex = 3;
  values[2] = 4 !== value, values[1] = 3 !== value, values[0] = 2 !== value
  result = [1]
  接下來,遍歷第二個值, value = 2, computed = 2, vlauesIndex = 3;
  values[2] = 4 !== value, values[1] = 3 !== value, values[0] = 2 == value
  當存在值相等的時候,直接跳轉到最外層,所以 result = [1]
  最後也就是說baseDifference([1, 2], [2, 3, 4]) = [1];
  看到 outer:是不是一下子懵了,這就是標籤語法,形式是 label: statement,這裏的標籤可以是除了保留字以外的任意標識符,當然語句也可以是任意語句。它有什麼用呢?這個標籤就相當於一個定位符,在 break, continue 後面用於指定跳轉的位置。

作者:就想叫菜鳥
鏈接:https://www.jianshu.com/p/8946dc5d884e
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

沒錯,這個並非我的解釋,我覺得這位作者寫得挺好的就引用了一下

  • isArrayLikeObject
/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

module.exports = isArrayLikeObject;

裏面又有一個isArrayLike的方法

  • isArrayLike
/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

module.exports = isArrayLike;

  isArrayLike方法比較簡單,你會發現裏面蹦出來個 isLength方法,這個我在這裏不過多介紹,是用來判斷數據長度是否是一個有限長度
  所以總的來說 isArrayLikeObject是判斷我們輸入的數據是不是一個數組或類數組結構,是則返回true,反之false

  • baseRest
/**
 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 */
function baseRest(func, start) {
  return setToString(overRest(func, start, identity), func + '');
}

module.exports = baseRest;

  這個函數主要是對剩餘參數的處理,它不用驗證參數或者強制輸入參數,這個我不過多解釋,大家理解就好

  那麼搞了這麼久,我們終於可以解釋 difference方法發執行過程了,首先就是傳出參數並進行 baseRest剩餘參數處理,讓後就是直接輸出,我們首先判斷array是不是數組,如果不是則返回空數組,如果是則進行下一步,將我們的 [values]通過 baseFlatten方法一級扁平化處理,最後通過 baseDifference方法取出唯一值


今天雖然只寫了一個方法,但是它依賴的方法太多了,一起解釋了一遍,今天就這樣了,明天繼續

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章