JavaScript實用庫:Lodash源碼數組函數解析(四)dropRight、dropWhile、dropRightWhile、baseWhile

本章內容主要是:dropRight、dropWhile、dropRightWhile、baseWhile

在這裏插入圖片描述

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

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

  


1、_.dropRight(array, [n=1])
這個方法和昨天的drop是類似的,但是,它是去除array尾部的n個元素。(n默認值爲1。)

下面我們來看它的例子:
在這裏插入圖片描述
和上次的drop的切片是類似的,大家理解一下
接下來看源碼:

/**
 * Creates a slice of `array` with `n` elements dropped from the end.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to query.
 * @param {number} [n=1] The number of elements to drop.
 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 * @returns {Array} Returns the slice of `array`.
 * @example
 *
 * _.dropRight([1, 2, 3]);
 * // => [1, 2]
 *
 * _.dropRight([1, 2, 3], 2);
 * // => [1]
 *
 * _.dropRight([1, 2, 3], 5);
 * // => []
 *
 * _.dropRight([1, 2, 3], 0);
 * // => [1, 2, 3]
 */
function dropRight(array, n, guard) {
  //獲取數組的長度
  var length = array == null ? 0 : array.length;
  //長度爲0輸出空數組
  if (!length) {
    return [];
  }
  //確定n的值
  n = (guard || n === undefined) ? 1 : toInteger(n);
  n = length - n;
  return baseSlice(array, 0, n < 0 ? 0 : n);
}
module.exports = dropRight;

前面的操作也和drop方法一樣,獲取array數組的長度,然後就是確定n的值,toInteger方法的源碼昨天說過了,大家可以去看看JavaScript實用庫:Lodash源碼數組函數解析(三) drop、toInteger、toFinite,這個方法就是將取整數方法。

drop方法不同的地方是:使用baseSlice方法進行切片時,起始位置與結束位置的不同。
我們的drop方法的起始位置是傳入參數n,結束位置是我們的數組array的長度length
而我們的dropRight方法的起始位置是0,也就是從頭開始,結束位置是數組array的長度length減去參數n
意思也特別的通俗易懂


2、.dropWhile(array, [predicate=.identity])
根據中文文檔介紹:它的作用是創建一個切片數組,去除array中從起點開始到 predicate 返回假值結束部分。predicate 會傳入3個參數: (value, index, array)。

接下來我們看例子

在這裏插入圖片描述
然後就是我們的源碼部分:

/**
 * Creates a slice of `array` excluding elements dropped from the beginning.
 * Elements are dropped until `predicate` returns falsey. The predicate is
 * invoked with three arguments: (value, index, array).
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to query.
 * @param {Function} [predicate=_.identity] The function invoked per iteration.
 * @returns {Array} Returns the slice of `array`.
 * @example
 *
 * var users = [
 *   { 'user': 'barney',  'active': false },
 *   { 'user': 'fred',    'active': false },
 *   { 'user': 'pebbles', 'active': true }
 * ];
 *
 * _.dropWhile(users, function(o) { return !o.active; });
 * // => objects for ['pebbles']
 *
 * // The `_.matches` iteratee shorthand.
 * _.dropWhile(users, { 'user': 'barney', 'active': false });
 * // => objects for ['fred', 'pebbles']
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.dropWhile(users, ['active', false]);
 * // => objects for ['pebbles']
 *
 * // The `_.property` iteratee shorthand.
 * _.dropWhile(users, 'active');
 * // => objects for ['barney', 'fred', 'pebbles']
 */
function dropWhile(array, predicate) {
  return (array && array.length)
    ? baseWhile(array, baseIteratee(predicate, 3), true)
    : [];
}

module.exports = dropWhile;

上面的例子太難看懂了,不夠直觀,現在我來舉個例子:

function less3(a) {
   return a < 3
}
_.dropWhile([1, 2, 5, 7, 4], less4)
// 從左側開始,開始索引爲less3返回值爲false時對應的索引,可知5調用less3時返回false,所以返回值爲:[5, 7, 4]


//然後我們順便提一下dropRightWhile
_.dropRightWhile([7, 2, 5, 2, 1], less4)
// 從右側開始,開始索引爲less3返回值爲false時對應的索引,可知5調用less3時返回false,所以返回值爲:[7, 2, 5]

所以我們可以看到,dropWhile方法是開始索引爲false,而dropRightWhile是結束索引爲false。

現在我直接將dropRightWhile的源碼寫出來,讓後最後提一下baseWhile方法纔可以解釋我們的過程


4、.dropRightWhile(array, [predicate=.identity])

根據中文文檔解釋,它的功能是:創建一個切片數組,去除array中從 predicate 返回假值開始到尾部的部分。predicate 會傳入3個參數: (value, index, array)。

這裏例子就不展示了,上面有提到過

現在直接上源碼;

/**
 * Creates a slice of `array` excluding elements dropped from the end.
 * Elements are dropped until `predicate` returns falsey. The predicate is
 * invoked with three arguments: (value, index, array).
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to query.
 * @param {Function} [predicate=_.identity] The function invoked per iteration.
 * @returns {Array} Returns the slice of `array`.
 * @example
 *
 * var users = [
 *   { 'user': 'barney',  'active': true },
 *   { 'user': 'fred',    'active': false },
 *   { 'user': 'pebbles', 'active': false }
 * ];
 *
 * _.dropRightWhile(users, function(o) { return !o.active; });
 * // => objects for ['barney']
 *
 * // The `_.matches` iteratee shorthand.
 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
 * // => objects for ['barney', 'fred']
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.dropRightWhile(users, ['active', false]);
 * // => objects for ['barney']
 *
 * // The `_.property` iteratee shorthand.
 * _.dropRightWhile(users, 'active');
 * // => objects for ['barney', 'fred', 'pebbles']
 */
function dropRightWhile(array, predicate) {
  return (array && array.length)
    ? baseWhile(array, baseIteratee(predicate, 3), true, true)
    : [];
}

module.exports = dropRightWhile;

4、_.baseWhile

我們直接來看源碼:

/**
 * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
 * without support for iteratee shorthands.
 *
 * @private
 * @param {Array} array The array to query.
 * @param {Function} predicate The function invoked per iteration.
 * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Array} Returns the slice of `array`.
 */
function baseWhile(array, predicate, isDrop, fromRight) {
  var length = array.length,
      // 判斷截取是從左側開始還是從右側開始,如果左側開始index爲-1,右側開始index取length
      index = fromRight ? length : -1;

  // 如果從左側開始截取,while循環如下:
  /* 
    while((++index < length) && predicate(array[index], index, array)){}
  */
  // index值不停的加1直到predicate(array[index], index, array)返回false時停止增加,或者index > length時停止增加
  // 此時如果isDrop爲true,最終執行結果爲slice(array, index, length)
  // 此時如果isDrop爲false,最終執行結果爲slice(array, 0, index)

  // 如果從右側開始截取,while循環如下:
  /* 
    while((index--) && predicate(array[index], index, array)){}
  */
  // index值不停的減1直到predicate(array[index], index, array)返回false時停止減小,或者index < 0時停止減小
  // 此時如果isDrop爲true,最終執行結果爲slice(array, 0, index + 1)
  // 此時如果isDrop爲false,最終執行結果爲slice(array, index+1, length)

  // predicate是個函數,在index變化過程中,它會對index對應的元素執行predicate函數,當predicate返回值爲true時繼續執行循環,當predicate爲false時結束循環
  
  while ((fromRight ? index-- : ++index < length) &&
    predicate(array[index], index, array)) {}

  return isDrop
    ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
    : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
}

module.exports = baseWhile;

所以我們可以根據baseWhile的四個參數確定數組的截取方向以及條件等。


最後的總結:
drop喫從左側開始截取,開始位置爲n,結束位置爲數組長度length

dropRight是從右側開始截取,開始位置爲0,結束位置爲數組長度length-n

dropWhile是從左側開始截取,開始位置爲數組中元素調用predicate方法時返回值爲false時對應的索引,結束位置爲數組長度length;

dropRightWhile是從右側開始截取,開始位置爲0,結束位置爲數組中元素調用predicate方法時返回值爲false時對應的索引加1;

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