preface

The chunk function in Lodash is a useful array-utility function that creates a new array, slicing and grouping the incoming arrays according to the size parameter. If the array is not divisible at the end, the rest of the elements are put in the last block

Although the principle of this function is relatively simple, in order to deal with some boundary cases in LoDash, it is very careful to do a lot of conditional judgment and processing for this function, so it is very robust, corresponding to similar array objects can also be processed

Thought analysis

Source code analysis

chunk

1. Pass in parameters:

  • arrayPassing in an array
  • sizePass in a number that determines the number of elements in the new array
  • guardPassed an iterator object that is intended to be used in conjunction with the iterative method

2. Source code analysis

function chunk(array, size, guard) {
  if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
    size = 1;
  } else {
    size = nativeMax(toInteger(size), 0);
  }
  var length = array == null ? 0 : array.length;
  if(! length || size <1) {
    return [];
  }
  var index = 0,
      resIndex = 0,
      result = Array(nativeCeil(length / size));
  while (index < length) {
    result[resIndex++] = baseSlice(array, index, (index += size));
  }
  
  return result;
}
Copy the code

The default size is 1 if guard is set or size is not set; If size is passed to anything else, it is cast as an integer

if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {    
  size = 1;
} else {
  size = nativeMax(toInteger(size), 0);
}
Copy the code

Check whether the array is empty, and then check whether the length attribute of the passed object exists, or whether size is negative, if not return the empty array

  var length = array == null ? 0 : array.length;
  if(! length || size <1) {
    return [];
  }
Copy the code

Class, copy the element in the specified position into the new array using the baseSlice method, and assign it to result. Returns result

var index = 0,
    resIndex = 0,
    result = Array(nativeCeil(length / size));
while (index < length) {
  result[resIndex++] = baseSlice(array, index, (index += size));
}
return result;
Copy the code

baseSlice

1. Pass in parameters

  • arrayPassing in an array
  • startIncoming copy starting point
  • endIncoming replication endpoint

2. Source code analysis

function baseSlice(array, start, end) {
  var index = -1,
      length = array.length;
  if (start < 0) {
    start = -start > length ? 0 : (length + start);
  }
  end = end > length ? length : end;
  if (end < 0) {
    end += length;
  }
  length = start > end ? 0 : ((end - start) >>> 0);
  start >>>= 0;
  var result = Array(length);
  while (++index < length) {
    result[index] = array[index + start];
  }
  return result;
}
Copy the code

Initialize, and convert both start and end to positive numbers. Note that if start and end were originally negative numbers, start and end numbers are terminated from the end of the array

  var index = -1,
      length = array.length;
  if (start < 0) {
    start = -start > length ? 0 : (length + start);
  }
  end = end > length ? length : end;
  if (end < 0) {
    end += length;
  }
Copy the code

Unsigned right shift to start, the sign bit of the end – start result becomes a positive number and is rounded. Since numbers store binary complement, it is equivalent to adding 2^32 to a negative result to ensure that it is non-negative (positive if meaningful, default 0 if meaningless). Then index starts at 0 and assigns the array element corresponding to the start position to the result element at index position

length = start > end ? 0 : ((end - start) >>> 0); start >>>= 0; Var result = Array(length); while (++index < length) { result[index] = array[index + start]; } return result; }Copy the code

Array like object

Since chunk can be used to group array-like objects, array-like objects are also briefly described here

First of all, we can explicitly define an array-like object that has a length attribute and its attributes are all non-negative integers.

The Chrome object display with the splice method is converted from {} to []

There is also a corresponding judgment method in LoDash, isArrayLike, which is to judge the length attribute, I will also analyze the opportunity in the future

Unlike arrays, the archetypal chain of array-like objects, or their inherited ancestor type, does not have Array, and therefore cannot use forEach, Map, reduce, etc., which requires a for loop or for loop to iterate over them… In the for… Of cannot be used unless Symbol. Iterator is defined, because the object itself needs to be iterable

You can append a custom symbol. iterator

To manipulate an array-like object, you can also convert it directly to an array, in addition to the methods described above. Array.from is the built-in function that handles this situation, passing in the argument returns a new Array of the original object attributes in order

More class array object in the result of the DOM selection, such as document. QuerySelectorAll returns a NodeList class array object

conclusion

As an array method, the chunk method is often used to group the slices of an array. You can upgrade the dimension of the array and divide the array into chunks

The robustness of the chunk method itself also ensures that it can be used in class arrays

Lodash reuses the baseSlice method in its underlying implementation, so the chunk method is O(n^2).