preface

Recently, I have been trying to improve my code skills. When I saw that there were some concerned leaders in Zhihu who analyzed the source code of an NPM package every day, I realized that I used Lodash in many places in my project, so I decided to read the source code of Lodash to see what details are worth learning from this large open source tool function library.

.internal

addMapEntry

/** * add key-value pairs ** to the map@private
 * @param {Object} Map Map to be modified@param {Array} Pair requires key-value pairs * to be added to the map@returns {Object} Returns the modified map */
function addMapEntry(map, pair) {
  Map. set cannot be returned because it cannot be chained in IE 11
  map.set(pair[0], pair[1]);
  return map;
}

export default addMapEntry;
Copy the code

addSetEntry

/** * adds the value ** to the set@private
 * @param {Object} Set Set to be modified@param {*} Value Specifies the value * to be added to the set@returns {Object} Return the modified set */
function addSetEntry(set, value) {
  Set.add cannot be returned because it cannot be chain-called in IE 11
  set.add(value);
  return set;
}

export default addSetEntry;
Copy the code

arrayEach

/** * dedicated version of array forEach function **@private
 * @param {Array} [array] Array to be traversed *@param {Function} Iteratee The function called in each iteration *@returns {Array} Returns the traversed array */
function arrayEach(array, iteratee) {
  let index = -1;
  const length = array.length;

  while (++index < length) {
    // when the iterated function returns false
    if (iteratee(array[index], index, array) === false) {
      break; }}return array;
}

export default arrayEach;
Copy the code

arrayEachRight

/** * a dedicated version of array forEachRight **@private
 * @param {Array} [array] Array to be traversed *@param {Function} Iteratee The function called in each iteration *@returns {Array} Returns the traversed array */
function arrayEachRight(array, iteratee) {
  let length = array == null ? 0 : array.length;

  while (length--) {
    // when the iterated function returns false
    if (iteratee(array[length], length, array) === false) {
      break; }}return array;
}

export default arrayEachRight;
Copy the code

arrayIncludes

import baseIndexOf from './baseIndexOf.js';

/** * A special version of array includes does not support specifying indexes **@private
 * @param {Array} [array] The array to search for *@param {*} Target Indicates the value to be searched *@returns {boolean} Returns true if target was found otherwise false */
function arrayIncludes(array, value) {
  // Takes advantage of JavaScript's automatic type conversion when ==
  // Filter undefined and null
  const length = array == null ? 0 : array.length;
  // Make use of JavaScript in! A feature that automatically performs type conversions
  // Convert length from number to Boolean
  return!!!!! length && baseIndexOf(array, value,0) > -1;
}

export default arrayIncludes;
Copy the code

This function introduces the baseIndexOf function, so the implementation of this function also needs to be understood.

import baseFindIndex from './baseFindIndex.js';
import baseIsNaN from './baseIsNaN.js';
import strictIndexOf from './strictIndexOf.js';

/** * The basic implementation of indexOf * does not support fromIndex boundary checking **@private
 * @param {Array} Array Array to find *@param {*} Value Indicates the value to be searched *@param {number} FromIndex finds the starting index *@returns {number} Returns the index if a matching value is found otherwise -1 */
function baseIndexOf(array, value, fromIndex) {
  // Take advantage of JavaScript NaN is not equal to NaN itself
  // Distinguishes nans from non-nans
  return value === value
    ? strictIndexOf(array, value, fromIndex)
    : baseFindIndex(array, baseIsNaN, fromIndex);
}

export default baseIndexOf;
Copy the code

Similarly, the baseIndexOf function introduced baseFindIndex, baseIsNaN, strictIndexOf functions, so the implementation of these functions also need to understand.

/** * a special version of indexOf * performs a strict equality comparison of values === **@private
 * @param {Array} Array Array to find *@param {*} Value Indicates the value to be searched *@param {number} FromIndex finds the starting index *@returns {number} Returns the index if a matching value is found otherwise -1 */
function strictIndexOf(array, value, fromIndex) {
  let index = fromIndex - 1;
  const {length} = array;

  while (++index < length) {
    if (array[index] === value) {
      returnindex; }}return -1;
}

export default strictIndexOf;
Copy the code
/** * The basic implementation of isNaN does not support the Number object **@private
 * @param {*} Value Indicates the value *@returns {boolean} Return true if the value is NaN otherwise false */
function baseIsNaN(value) {
  // Take advantage of JavaScript NaN is not equal to NaN itself
  // Distinguishes nans from non-nans
  returnvalue ! == value; }export default baseIsNaN;
Copy the code
/** * Basic implementation of findIndex and findLastIndex **@private
 * @param {Array} Array Array to find *@param {Function} The function called by the predicate each iteration *@param {number} FromIndex finds the starting index *@param {boolean} [fromRight] specifies the search direction fromRight to left *@returns {number} Returns the index if a matching value is found otherwise -1 */
function baseFindIndex(array, predicate, fromIndex, fromRight) {
  const {length} = array;
  let index = fromIndex + (fromRight ? 1 : -1);

  while (fromRight ? index-- : ++index < length) {
    if (predicate(array[index], index, array)) {
      returnindex; }}return -1;
}

export default baseFindIndex;
Copy the code