lodash里的rest方法

149 阅读2分钟

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

前言

本篇章我们将了解lodash里的rest方法使用和实现,在了解内部源码的过程中学习封装思想和重构手法。

rest方法主要是创建一个函数,调用参数func时,this绑定到创建的新函数,并且使用第二个参数start之后的参数作为数组传入。

参数说明:

  • 参数1:函数类型,表示应用rest参数的函数。
  • 参数2:数字类型,表示rest参数的起始位置,默认值为[start=func.length-1]。

使用如下:

var say = _.rest(function(what, names) {
  return what + ' ' + _.initial(names).join(', ') +
    (_.size(names) > 1 ? ', & ' : '') + _.last(names);
});
 
say('hello', 'fred', 'barney', 'pebbles');
// => 'hello fred, barney, & pebbles'

实现上,对于非函数类型的参数直接抛出错误,内部会先对参数start进行初始化赋值,会将其转换为整数,最后会返回baseRest的调用结果。

源码如下:

import baseRest from './_baseRest.js';
import toInteger from './toInteger.js';

var FUNC_ERROR_TEXT = 'Expected a function';

function rest(func, start) {
  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  start = start === undefined ? start : toInteger(start);
  return baseRest(func, start);
}

baseRest

baseRest是rest方法的基本实现,接收的参数和rest方法保持一致,内部会调用overRest和setToString方法,而identity方法则是返回传递的参数,方便后续方法迭代时调用。

import identity from './identity.js';
import overRest from './_overRest.js';
import setToString from './_setToString.js';

function baseRest(func, start) {
  return setToString(overRest(func, start, identity), func + '');
}

overRest

overRest方法是baseRest方法的专用版本,用于转换rest数组。其中第一个参数和第二个参数跟rest方法以及baseRest方法一致,该方法有第三个参数,表示转换rest数组。

import apply from './_apply.js';

var nativeMax = Math.max;

function overRest(func, start, transform) {
  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
  return function() {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = transform(array);
    return apply(func, this, otherArgs);
  };
}

apply

function apply(func, thisArg, args) {
  switch (args.length) {
    case 0: return func.call(thisArg);
    case 1: return func.call(thisArg, args[0]);
    case 2: return func.call(thisArg, args[0], args[1]);
    case 3: return func.call(thisArg, args[0], args[1], args[2]);
  }
  return func.apply(thisArg, args);
}

setToString

setToString方法我们在《 lodash里的内部方法getFuncName和setToString 》中已经了解,这里就不多做赘述。

小结

本篇章我们通过了解rest方法的使用和源码实现,学习了其核心方法beseRest的实现,同时也了解到内部方法overRest和setToString 的实现,在学习源码的过程中理解lodash封装思想和函数提炼等手法。