1 简介
Lodash是一款优秀的 JavaScript 工具库,里面包含了大量的工具函数。在 2015 年就成为被依赖最多的 JavaScript 库,写这篇文档是最新版是 4.17.4,适用于常见浏览器以及 Node.js 等。
这里给出其英文文档和中文文档的链接。其中中文文档的版本较低,但是区别不大,可以参考帮助理解。
2 常见用法
在这部分我们介绍一些 Lodash 的常见的优雅的用法。主要是引起大家的学习兴趣,有更多优雅用法等待大家去发现。
_.get
获取一个嵌套很深的字段
1 | //config 初始化为 null,需要从服务器端获取权限数据 |
对应地,可以通过_.set({}, 'a.b.c', 1)
创建一个多级嵌套的对象。
_.map
获取数组中每个对象的特定字段,并形成一个新的数组
1 | //使用所有用户的 idCard 字段创建出一个数组 |
_.pick
取出对象的部分字段形成一个新对象
1 | //在修改密码表单里,用户输入了如下字段并被封装到一个对象中 |
对应地,还有_.omit
方法表示删除部分字段形成一个新对象。
_.random
获取一个随机值
1 | //获取[90, 100)之内的一个随机值 |
类似地,_.sample(['a', 'b', 'c'])
可以从数组中随机取出一个项目。
_.clamp
将一个数字修改成区间中的一个值
1 | //使用原生JS |
_.once
确保一个函数只会执行一次
1 | //使用原生JS |
_.chain
链式操作
链接调用让代码更加整洁;避免了中间变量,避免了错误引用,让代码质量更有保证;_.chain
还提供了延迟计算特性,在显式或隐式调用value()
方法之前是不进行任何计算的,通过合并大大降低迭代次数。
下面是lodash
的官方文档中的一个例子。
1 | var users = [{ user: 'barney', age: 36 }, { user: 'fred', age: 40 }, { user: 'pebbles', age: 1 }]; |
3 模块
Lodash 的工具函数很多,可以分为以下几类:数组(Array),集合(Collection),函数(Function),Lang(Lang),数学(Math),数字(Number),对象(Object),字符串(String),未分类工具函数(Util)。下面将会按类别介绍常见工具函数。
4 数组
获取子数组
函数名 | 简介 |
---|---|
slice | 获取元素第 m-n(不包含)个元素 |
tail | 获取出第一个元素之外的其他元素 |
initial | 获取出最后一个元素之外的其他元素 |
take | 从左侧开始获取任意数量的元素 |
takeRight | 从右侧开始获取任意数量的元素 |
takeWhile | 从左侧开始获取任意数量的元素,直到断言返回假值 |
takeRightWhile | 从右侧开始获取任意数量的元素,直到断言返回假值 |
drop | 丢掉前面几个元素,得到剩余元素 |
dropWhile | 丢掉前面几个元素知道迭代器返回假值,得到剩余元素 |
dropRight | 丢掉后面几个元素,得到剩余元素 |
dropRightWhile | 丢掉后面几个元素知道迭代器返回假值,得到剩余元素 |
数组常见操作
操作 | 不修改原数组 | 修改原数组 |
---|---|---|
移除 | without | pull |
相减 | difference | pullAll |
相减 | differenceBy | pullAllBy |
相减 | differenceWith | pullAllWith |
反转 | reverse | |
裁剪 | at | pullAt |
过滤 | filter | remove |
数组常见操作变种函数 by, with
有些函数还可以稍微变化一下,接受不同的参数,提供更多灵活性。
作用 | 函数名 | by | with |
---|---|---|---|
相减 | difference | differenceBy | differenceWith |
交集 | intersection | intersectionBy | intersectionWith |
并集 | union | unionBy | unionWith |
异或 | xor | xorBy | xorWith |
相减 | pullAll | pullAllBy | pullAllWith,跟difference不同的是,pullAll修改原数组 |
去重 | uniq | uniqBy | uniqWith |
去重 | sortedUniq | sortedUniqBy |
获取数组某个位置上的元素
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
head | 数组=>元素 | 返回数组的第一个元素,和first相同 |
last | 数组=>元素 | 返回数组的最后一个元素,和head相反 |
nth | 数组=>元素 | 返回数组中某个位置上的元素 |
检测元素在数组中的索引
函数名 | 简介 |
---|---|
indexOf | 获取元素在数组中的索引 |
sortedIndexOf | 和indexOf功能一致,只是通过二分搜索方法 |
lastIndexOf | 获取元素在数组中的索引,最后一次出现 |
sortedLastIndexOf | 和lastIndexOf功能一致,只是通过二分搜索方法 |
findIndex | 寻找元素位置 |
findLastIndex | 寻找元素位置,从后往前 |
检测元素在插在有序数组的什么位置
函数名 | 简介 |
---|---|
sortedIndex | 通过二分搜索判断元素应该插在数组的哪个位置 |
sortedIndexBy | 同上,可以额外提供一个迭代器函数 |
sortedLastIndex | 和sortedIndex类似,但是从右边开始 |
sortedLastIndexBy | 同上,可以额外提供一个迭代器函数 |
将数组拍平
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
flatten | 高维数组=>低维数组 | 将数组拍平 |
flattenDeep | 高维数组=>数组 | 将数组拍平 |
flattenDepth | 高维数组=>低维数组 | 将数组拍平 |
Zip
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
zip | 多个数组=>二维数组 | 可以理解为二维数组的行列互换 |
zipWith | 多个数组=>数组 | 同上,但是可以自由处理行列互换后的数组中的每个数组元素 |
zipObject | 两个数组=>对象 | 把 keys 和 values 数组组成一个新对象 |
zipObjectDeep | 两个数组=>对象 | 同上,递归地处理属性名 |
未分类函数
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
chunk | 数组=>二维数组 | 分段形成二维数组 |
compact | 数组=>数组 | 移除假值 |
concat | 多个数组=>数组 | 连接多个数组形成一个数组 |
fill | 数组=>数组 | 填充数组 |
fromPairs | 二维数组=>对象 | 将键值数组变成对象。和toPairs相反 |
join | 数组=>字符串 | 拼接数组元素成一个字符串 |
5 集合
为什么区分集合函数和数组函数?
集合函数不单单适用于数组,还适用于字符串,对象,类数组对象(比如 Arguments,NodeList 等)。字符串是字符的集合,对象是属性值的集合。类数组对象是通过“鸭子类型”工作的,所以如果你传入一个拥有length
字段并且值为数字的对象,这个对象会被当做一个数组处理。具体请参考Underscore.js文档。
范例:
1 | function printKeyVal(val, key) { |
下面将分类介绍集合相关函数。
遍历
函数名 | 简介 |
---|---|
each | 同forEach |
eachRight | 同forEachRight |
排序
函数名 | 简介 |
---|---|
sortBy | 排序 |
orderBy | 同sortBy,还可以指定正序倒序 |
shuffle | 返回一个打乱顺序的新数组 |
过滤
函数名 | 简介 |
---|---|
filter | 创建一个新数组,包含了所有让断言为真的元素 |
reject | 创建一个新数组,包含了所有让断言为假的元素 |
partition | 根据断言真假将一个集合分成两个集合 |
Map 之后再 flatten
函数名 | 简介 |
---|---|
flatMap | map之后再flatten |
flatMapDeep | map之后再flattenDeep |
flatMapDepth | map之后再flattenDepth |
寻找元素
函数名 | 简介 |
---|---|
find | 找到第一个让断言为真的元素 |
findLast | 同上,逆序 |
随机取值
函数名 | 简介 |
---|---|
sample | 从集合中随机选出一个元素 |
sampleSize | 从集合中随机选出 n 个元素 |
迭代
函数名 | 简介 |
---|---|
reduce | |
reduceRight | - |
分组计数
函数名 | 简介 |
---|---|
countBy | 返回一个对象,属性名是迭代器的返回值,属性值该返回值出现的次数 |
groupBy | 返回一个对象,属性名是迭代器的返回值,属性值是一个包含了相应元素的数组 |
未分类
函数名 | 简介 |
---|---|
keyBy | 返回一个对象,属性名是迭代器的返回值,属性值是元素本身 |
some | 对于集合中的每个元素,是否至少其一返回真值 |
every | 对于集合中的每个元素,是否都返回真值 |
includes | 判断元素是不是在数组中,判断某个值是不是某个对象的属性值,判断一个字符串是不是包含在另一个字符串中 |
map | 对集合的数组 |
invokeMap | - |
6 对象
仅需要部分字段
函数名 | 简介 |
---|---|
omit | 通过忽略某些字段创建一个新对象 |
omitBy | |
pick | 通过指定某些字段创建一个新对象 |
pickBy | - |
合并对象
函数名 | 简介 |
---|---|
assign | 合并对象 |
assignWith | 有条件地合并对象 |
extend | 合并对象,包括原型链上的属性 |
extendWith | 有条件地合并对象,包括原型链上的属性 |
assignIn | 别名extend |
assignInWith | 别名extendWith |
defaults | 合并对象,将后面参数的属性付给第一个参数,如果第一个参数没有相应属性的话 |
defaultsDeep | 递归地合并对象,将后面参数的属性付给第一个参数,如果第一个参数没有相应属性的话 |
merge | 递归地合并对象,将后面参数的属性付给第一个参数 |
mergeWith | 同merge,额外接受一个 customizer 参数 |
键值列表
函数名 | 简介 |
---|---|
keys | 创建一个数组,包含对象中所有的属性 |
keysIn | 创建一个数组,包含对象中所有的属性(包含原型链上的) |
functions | 创建一个数组,包含对象中所有值为函数的属性 |
functionsIn | 创建一个数组,包含对象中所有值为函数的属性(包含原型链上的) |
values | 创建一个数组,包含对象中所有的属性值 |
valuesIn | 创建一个数组,包含对象中所有的属性值(包含原型链上的) |
赋值取值
函数名 | 简介 |
---|---|
at | 获取对象的一组属性路径的值,肯定不会报错 |
get | 获取对象的某个属性路径的值,肯定不会报错 |
result | 同get,但是如果属性值是函数的话,自动执行该函数 |
set | 设置对象的某个属性路径的值 |
setWith | 设置对象的某个属性路径的值,遇到不存在的中间对象,使用数组呢?还是使用对象呢?等等 |
update | 同set,只是接受一个函数作为参数 |
updateWith | 同setWith,只是接受一个函数作为参数 |
unset | 删除对象的某个属性路径 |
invoke | 调用对象中某个属性路径上的函数,肯定不会报错 |
键值数组
函数名 | 简介 |
---|---|
entries | {‘a’:1}=>[[‘a’,1]]。别名toPairs |
entriesIn | 同上,但是包含原型链上的属性。别名toPairsIn |
键值变换
函数名 | 简介 |
---|---|
mapKeys | 对对象中所有属性名做某种处理之后形成一个新对象 |
mapValues | 对对象中所有属性值做某种处理之后形成一个新对象 |
invert | 将对象中的属性名和属性值互换转成一个新对象 |
invertBy | 同invert,但是转换以后的属性值是原属性值组成的数组 |
键值遍历
函数名 | 简介 |
---|---|
forIn | 遍历对象上的所有属性,包含原型链上的。 |
forInRight | 遍历对象上的所有属性,包含原型链上的。 |
forOwn | 遍历对象上的所有属性,不包含原型链上的。 |
forOwnRight | 遍历对象上的所有属性,不包含原型链上的。 |
寻找属性
函数名 | 简介 |
---|---|
findKey | 同find类似,但是匹配的是对象的属性值,返回的是对象的属性名 |
findLastKey | 同findKey类似,但是匹配的是对象的属性值,返回的是对象的属性名 |
判断属性是否存在
函数名 | 简介 |
---|---|
has | 判断对象上是否拥有某个属性,不包含原型链上的 |
hasIn | 判断对象上是否拥有某个属性,包含原型链上的 |
转换对象或数组
函数名 | 简介 |
---|---|
transform | 同reduce,但是其迭代器函数返回的是布尔值,如果返回 false,则停止迭代 |
创建新对象
函数名 | 简介 |
---|---|
create | 创建一个对象,并指定其原型和属性 |
7. 函数
修改参数
函数名 | 简介 |
---|---|
ary | 创建一个包裹函数,只将前 n 个参数传递给原函数。 |
unary | 创建一个包裹函数,只将第一个参数传递给原函数。 |
flip | 创建一个包裹函数,将参数逆序之后传递给原函数。 |
rearg | 创建一个包裹函数,调整参数顺序之后在传递给原函数 |
rest | 创建一个包裹函数,将参数合成数组之后传递给原函数 |
spread | 创建一个包裹函数,将数组参数展开之后传给原函数,跟rest相反 |
overArgs | 创建一个包裹函数,将参数做处理之后再传递给原函数。 |
修改结果
函数名 | 简介 |
---|---|
negate | 创建一个包裹函数,返回原函数结果的非。 |
缓存结果
函数名 | 简介 |
---|---|
memoize | 创建一个包裹函数,会缓存计算结果 |
降频调用
函数名 | 简介 |
---|---|
debounce | |
throttle |
延迟调用
函数名 | 简介 |
---|---|
defer | 类似setTimeout(fn,0) ,可以指定参数 |
delay | 类似setTimeout(fn,x) ,可以指定参数 |
延迟调用
函数名 | 简介 |
---|---|
once | 创建一个包裹函数,确保原函数只被执行一次。 |
before | 创建一个包裹函数,确保原函数只被执行 n 次。 |
after | 创建一个包裹函数,调用包裹函数时只有 n 次之后才会调用目标函数 |
固定参数
函数名 | 简介 |
---|---|
wrap | 创建一个包裹函数,固定原函数的第一个参数 |
partial | 创建一个包裹函数,固定原函数若干个参数 |
partialRight | 创建一个包裹函数,固定原函数若干个参数 |
bind | 创建一个包裹函数,固定原函数若干个参数,并指定 this 对象 |
bindKey | 和bind功能类似,但是能够处理尚未创建或被重写的函数,有点事件代理的感觉。 |
curry | 创建一个包裹函数,可以传入任意数量的参数,如果参数不完整,则返回一个接受余下参数的新函数,否则,调用原函数获得计算结果。 |
curryRight | 同上,逆序 |
8. 字符串
书写格式
函数名 | 简介 |
---|---|
startCase | 每个单词首字母大写,多用于标题 |
camelCase | 小驼峰 |
kebabCase | 小写连字符 |
snakeCase | 小写下划线 |
upperCase | 大写加空格 |
lowerCase | 小写加空格 |
大写小写
函数名 | 简介 |
---|---|
capitalize | 首字母大写,其余小写 |
upperFirst | 首字母大写,其余不变 |
lowerFirst | 首字母小写,其余不变 |
toUpper | 大写 |
toLower | 小写 |
打头结尾
函数名 | 简介 |
---|---|
endsWith | 是不是以特定字符串结尾 |
startsWith | 是不是以特定字符串打头 |
转义
函数名 | 简介 |
---|---|
escape | 转义 &<>”‘,与unescape相反 |
escapeRegExp | 转义正则表达式中的特殊字符:^\$.*+?()[]{}\ |
补全抹掉
函数名 | 简介 |
---|---|
pad | 使用某个字符串将特定字符串扩充至指定长度,类似地还有padStart,padEnd |
trim | 去除字符串两边的特殊字符(默认为空格),类似地还有trimStart,trimEnd |
未分类
函数名 | 简介 |
---|---|
parseInt | 转成整型 |
repeat | 将某个字符串重复 n 遍 |
replace | 替换字符串 |
split | 拆分字符串 |
template | 简单模板引擎 |
truncate | 截断字符串 |
words | 将字符串拆分成单词,可以指定拆分模式 |
deburr | 基本拉丁字母 |
9. 数字
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
clamp | 数字=>数字 | 将数字限定在一个范围内 |
inRange | 数字=>布尔 | 判断数字是否在某个区间里 |
random | 区间=>数字 | 随机获取一个值,可以通过第三个参数指定是不是返回小数 |
10. 数学
加减乘除
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
add | 两个数字 => 数字 | 返回两个数字的和 |
subtract | 两个数字 => 数字 | 返回两个数字的差 |
multiply | 两个数字 => 数字 | 返回两个数字的积 |
divide | 两个数字 => 数字 | 返回两个数字的商 |
和,最大值,最小值,平均值
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
sum | 数组 => 数字 | 返回数组中的各数字之和 |
max | 数组 => 数字 | 返回数组中的最大值 |
min | 数组 => 数字 | 返回数组中的最小值 |
mean | 数组 => 数字 | 返回数组中的平均值 |
数字精度
函数名 | 主要参数-返回值 | 简介 |
---|---|---|
ceil | 数字 => 数字 | 向上取整,可以指定精度 |
floor | 数字 => 数字 | 向下取整,可以指定精度 |
round | 数字 => 数字 | 四舍五入取整,可以指定精度 |
11. 语言
数值比较
函数名 | 简介 |
---|---|
eq | 等价于=== |
isEqual | 深度比较对象是否相等 |
isEqualWith | 深度比较对象是否相等,可以定义相等比较函数 |
gt | 大于 |
lt | 小于 |
gte | 大于等于 |
lte | 小于等于 |
类型判断
函数名 | 简介 |
---|---|
isArguments | |
isArray | |
isArrayBuffer | |
isArrayLike | |
isArrayLikeObject | |
isBoolean | |
isBuffer | |
isDate | |
isElement | |
isEmpty | 判断是否有可遍历的属性 |
isError | 错误 |
isFinite | 是否是有限的数字,基于 Number.isFinite |
isFunction | |
isInteger | |
isLength | |
isMap | |
isMatch | |
isMatchWith | |
isNaN | |
isNative | 原生函数 |
isNil | 等价于 _.isNull(val) || _.isUndefined(val) |
isNull | |
isNumber | |
isObject | |
isObjectLike | |
isPlainObject | |
isRegExp | |
isSafeInteger | |
isSet | isSet |
isString | |
isSymbol | |
isTypedArray | |
isUndefined | |
isWeakMap | |
isWeakSet |
类型转换
函数名 | 简介 |
---|---|
castArray | 强制转给数组 |
toArray | 转成数组,对象调用 Object.values,字符串转成字符数组 |
toFinite | |
toInteger | |
toLength | |
toNumber | |
toPlainObject | |
toSafeInteger | |
toString | 转成字符串, |
复制对象
函数名 | 简介 |
---|---|
clone | |
cloneDeep | |
cloneDeepWith | |
cloneWith |
检测对象
函数名 | 简介 |
---|---|
conformsTo | 判断一个对象的字段是否满足一些条件 |
12. 工具
总是返回某个参数的函数
函数名 | 简介 |
---|---|
constant | 创建一个包裹函数,总是返回第一个参数 |
nthArg | 创建一个包裹函数,总是返回第 n 个参数 |
总是返回某个特定值的函数
函数名 | 简介 |
---|---|
noop | 总是返回undefined 的函数 |
stubArray | 总是返回空数组的函数 |
stubObject | 总是返回空对象的函数 |
stubString | 总是返回空字符串的函数 |
stubTrue | 总是返回true 的函数 |
stubFalse | 总是返回false 的函数 |
identity | 总是返回第一个参数 |
获取对象的属性值或者调用对象的函数
函数名 | 简介 |
---|---|
method | _.invoke(object, path, [args])预设path 和args 两个参数 |
methodOf | _.invoke(object, path, [args])预设object 和args 两个参数 |
property | _.get(object, path)预设path参数,不同的是缺少 defaultValue`参数 |
propertyOf | _.get(object, path)预设object 参数,不同的是缺少defaultValue 参数 |
判断对象是否满足某些条件
函数名 | 简介 |
---|---|
conforms | 创建一个包裹函数,判断一个对象的字段是否满足某个函数。conforms 意思是遵守。 |
matches | 创建一个包裹函数,判断一个对象的字段是否等于某个值,使用isEqual判断是否相等。跟isMatch类似 |
matchesProperty | 创建一个包裹函数,判断一个对象特定字段是否等于某个值,使用isEqual判断是否相等。 |
把多个操作合成一个操作
函数名 | 简介 |
---|---|
flow | 把一组函数串起来形成一个新函数 |
flowRight | 同上,倒序 |
批量进行多个操作
函数名 | 简介 |
---|---|
over | 创建一个新函数,并将参数传递给预先指定的一组函数,并返回其结果 |
overEvery | 跟over 类似,判断是不是所有函数都返回真值 |
overSome | 跟over 类似,判断是不是至少一个函数返回真值 |
等差数列
函数名 | 简介 |
---|---|
range | 生成等差数列,可以指定步长,步长可以是小数,也可以是负数 |
rangeRight | 这个基本可以忽略,功能完成可以由range代替。 |
其他未分类
函数名 | 简介 |
---|---|
attempt | 使用 try-catch 包裹函数,如果出错返回错误对象 |
bindAll | 将一个对象的多个函数中的 this 固定为该对象 |
cond | 创建一个拥有复杂 if-else 的函数 |
defaultTo | 如果第一个参数为 NaN,null,undefined,则返回第二个参数,否则返回第一个参数 |
iteratee | 创建一个迭代函数 |
noConflict | 如果_ 被占用,可以使用该方法 |
runInContext | 创建一个lodash 镜像对象,可以扩展修改该对象 |
mixin | 给一个对象的原型添加属性或方法,一般配合runInContext扩展lodash 。 |
times | 执行函数 n 次,传入参数为 index |
toPath | ‘a[0].b.c’=>[‘a’,’0’,’b’,’c’] |
uniqueId | 生成唯一 ID,可以指定前缀 |
13. 链式
链式调用的好处
省略了中间变量,让代码更加简洁,更加安全。
链式调用可以优化成惰性求值(延迟计算),让代码更加高效。
_(value)
创建一个经过 lodash 包装过后的对象会启用隐式链,直到调用了不支持链接调用的函数或者主动调用value
方法解除链式调用。
作用类似于chain
lodash 包装对象上的特殊函数
函数名 | 简介 |
---|---|
tap | 可以在链式调用中插入普通方法,直接修改中间结果,也可以仅仅是用于调试打印中间结果 |
thru | 同tap,但是使用函数的返回值作为中间结果 |
commit | 立即执行链式调用中尚未进行的操作 |
next | 获得包装对象的下一个值 |
plant | 复制一个链式调用,并传入初始值 |
value | 结束链式调用,并计算结果。别名valueOf ,toJSON |