lodash里的slice方法

148 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第33天,点击查看活动详情

前言

lodash里的slice方法主要是裁剪数组array,从 start 位置开始到end结束,但不包括 end 本身的位置,该方法用于代替Array.prototype.slice来确保数组正确返回。

参数说明:

  • 参数1:数组类型,表示要切片的数组。
  • 参数2:数字类型,起始位置,默认为0。
  • 参数3:数字类型,结束位置,默认为数组长度。

slice方法实现上,先判断参数数组是否为null,为null的话直接返回空数组,同时参数数组长度为0时也返回空数组。其次会调用isIterateeCall判断参数是否符合迭代调用,对于非整数的参数会调用toInteger对参数进行处理,最终会返回核心方法baseSlice的调用结果。

源码如下:

import baseSlice from './_baseSlice.js';
import isIterateeCall from './_isIterateeCall.js';
import toInteger from './toInteger.js';


function slice(array, start, end) {
  var length = array == null ? 0 : array.length;
  if (!length) {
    return [];
  }
  if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
    start = 0;
    end = length;
  }
  else {
    start = start == null ? 0 : toInteger(start);
    end = end === undefined ? length : toInteger(end);
  }
  return baseSlice(array, start, end);
}

baseSlice

baseSlice方法是_.slice方法的基本实现。

源码如下:


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;
}

isIterateeCall

isIterateeCall方法主要是检查给定参数是否来自iteratee调用,如果参数来自iteratee调用,则返回true。

参数说明:

  • 参数1:任意类型,表示潜在的迭代对象值参数。
  • 参数2:任意类型,表示潜在的迭代对象索引或键参数。
  • 参数3:对象类型,表示潜在的iteratee对象参数。

源码如下:

import eq from './eq.js';
import isArrayLike from './isArrayLike.js';
import isIndex from './_isIndex.js';
import isObject from './isObject.js';


function isIterateeCall(value, index, object) {
  if (!isObject(object)) {
    return false;
  }
  var type = typeof index;
  if (type == 'number'
        ? (isArrayLike(object) && isIndex(index, object.length))
        : (type == 'string' && index in object)
      ) {
    return eq(object[index], value);
  }
  return false;
}

eq

eq方法是判断两个值是否相等。

源码如下:

function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

isIndex

isIndex方法主要是检查参数value是否是有效的类数组索引。

源码如下:

var MAX_SAFE_INTEGER = 9007199254740991;

var reIsUint = /^(?:0|[1-9]\d*)$/;

function isIndex(value, length) {
  var type = typeof value;
  length = length == null ? MAX_SAFE_INTEGER : length;

  return !!length &&
    (type == 'number' ||
      (type != 'symbol' && reIsUint.test(value))) &&
        (value > -1 && value % 1 == 0 && value < length);
}

isObject

isObject方法主要通过typeof操作符判断数据是否属于对象类型。

源码如下:

function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

isArrayLike

在《 lodash里的is系列(一) 》中我们已经了解到isArrayLike方法的实现。

小结

本篇章我们主要通过了解slice方法的实现,同时认识了其核心baseSlice内部方法以及isIterateeCall内部方法的实现。