携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情
前言
lodash里的内部方法createRecurry,主要是创建一个函数,该函数包装参数func以继续柯里化。
参数说明:
- 参数1:函数类型,表示要包装的函数。
- 参数2:数字类型,表示位掩码标志。
- 参数3:函数类型,表示用于创建
func包装器的函数。 - 参数4:任意类型,表示占位符值
- 参数5:任意类型,表示参数
func的this绑定。 - 参数6:数组类型,表示提供给前面参数的参数数组。
- 参数7:数组类型,表示参数6
partials的占位符索引。 - 参数8:数组类型,表示新函数的参数位置。
- 参数9:数字类型,表示参数
func的算术上限。 - 参数10:数字类型,表示表示参数
func的数量。
该方法实现借助isLaziable、setData、setWrapToString方法,我们先了解各自方法的实现。关于setData的实现可以在《 lodash里内部方法getData和setData的实现 》中了解,而setWrapToString方法主要是设置参数wrapper的“toString”方法以模拟“reference”的源。
isLaziable
isLaziable方法可以检查参数func是否有惰性对应项。
该方法实现借助了LazyWrapper、getData、getFuncName、lodash等内部方法。其中getData方法在《 lodash里内部方法getData和setData的实现 》中已经了解其实现。
LazyWrapper
LazyWrapper方法可以创建一个延迟包装器对象,该对象包装参数value以启用延迟计算。
实现上借助baseCreate方法和baseLodash方法。其中,baseCreate方法在 《 lodash里的内部方法createBind 》中已经了解到。而baseLodash表示一个包装器继承自函数。
function baseLodash() {}
LazyWrapper源码如下:
import baseCreate from './_baseCreate.js';
import baseLodash from './_baseLodash.js';
var MAX_ARRAY_LENGTH = 4294967295;
function LazyWrapper(value) {
this.__wrapped__ = value;
this.__actions__ = [];
this.__dir__ = 1;
this.__filtered__ = false;
this.__iteratees__ = [];
this.__takeCount__ = MAX_ARRAY_LENGTH;
this.__views__ = [];
}
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
LazyWrapper.prototype.constructor = LazyWrapper;
isLaziable源码实现
import LazyWrapper from './_LazyWrapper.js';
import getData from './_getData.js';
import getFuncName from './_getFuncName.js';
import lodash from './wrapperLodash.js';
function isLaziable(func) {
var funcName = getFuncName(func),
other = lodash[funcName];
if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
return false;
}
if (func === other) {
return true;
}
var data = getData(other);
return !!data && func === data[0];
}
createRecurry源码实现
import isLaziable from './_isLaziable.js';
import setData from './_setData.js';
import setWrapToString from './_setWrapToString.js';
var WRAP_BIND_FLAG = 1,
WRAP_BIND_KEY_FLAG = 2,
WRAP_CURRY_BOUND_FLAG = 4,
WRAP_CURRY_FLAG = 8,
WRAP_PARTIAL_FLAG = 32,
WRAP_PARTIAL_RIGHT_FLAG = 64;
function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
var isCurry = bitmask & WRAP_CURRY_FLAG,
newHolders = isCurry ? holders : undefined,
newHoldersRight = isCurry ? undefined : holders,
newPartials = isCurry ? partials : undefined,
newPartialsRight = isCurry ? undefined : partials;
bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
}
var newData = [
func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
newHoldersRight, argPos, ary, arity
];
var result = wrapFunc.apply(undefined, newData);
if (isLaziable(func)) {
setData(result, newData);
}
result.placeholder = placeholder;
return setWrapToString(result, func, bitmask);
}
小结
本篇章我们了解到createRecurry方法的实现,内部调用封装的isLaziable、setData、setWrapToString方法,实现了参数func的柯里化。