lodash 起步(数组)

Lodash 是一个较为流行的 JavaScript 的实用工具库。

在开发过程中如果能熟练使用一些工具库提供的方法,有利于提高开发效率

笔者从 API 上入手,不分析其源码,先从全局的角度来体验、研究它。分析 API 的命名特性、哪些方法有用,哪些又是比较鸡肋,仅代表笔者个人意见。

Tip:根据Lodash 中文文档得知,API 主要分为:数组、集合、函数、语言、数学、数字、对象、Seq、字符串、实用函数等约10个部分。而数组在我们编程过程中具有非常重要的地位,故笔者决定先从其入手。

环境准备

直接通过引用 bootstrap 免费的 cdn 的方式进行,只需两个文件:index.htmltest-array.js。内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script src="./test-array.js"></script>
</head>
<body> </body>
</html>
let r

// 封装 console.log,使之更剪短
const l = (...ops) => {
console.log(...ops)
} {
r = _.VERSION
// => 4.17.21
l(r)
} {
r = _.join(['a', 'b', 'c'], '~');
// => 'a~b~c'
l(r)
}

Tip: 所有测试都是如上结构

api 设计特性分析

  1. 有的方法可能是考虑兼容性,比如 _.fill,但 javascript 也有对应的原生方法(Array.prototype.fill),倘若使用 babel 库帮忙转换,那这类方法就有些鸡肋
  2. 命名系列化。比如下文的 _.sortedIndex 系列,有 .sortedIndex、.sortedIndexOf、.sortedLastIndexOf、.sortedIndexBy、.sortedLastIndex、.sortedLastIndexBy 共6个,核心是 _.sortedIndex,通常系列方法有功能增强版,例如这里的 _.sortedIndexBy,而命名中有 Last 通常从后往前查找
  3. 系列化的 api 通常有基础版和加强版。例如 _.difference 系列,_.differenceBy_.differenceWith都是加强版
  4. 提供简写进一步提高代码简洁性,比如下面的 _.isEqual
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
_.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
// => [{ 'x': 2, 'y': 1 }]

数组 api 总览

仅列出非鸡肋方法:

Tip: 笔者认为可以用原生方法非常便捷的替换的 api 就是鸡肋。

  • _.chunk - 分块。将数组(array)拆分成多个 size 长度的区块,并将这些区块组成一个新数组
  • _.compact - 压紧。创建一个新数组,包含原数组中所有的非假值元素
  • _.difference 系列 - 。从第一个数组中排除给定数组中的值
  • _.drop 系列 - 减小。例如去除数组前面两个元素
  • _.fromPairs/_.toPair - 一双。例如 [['fred', 30], ['barney', 40]] <---> { 'fred': 30, 'barney': 40 }
  • _.intersection 系列 - 交集
  • _.pull - 移除数组中的值
  • _.sortedIndex - value 应插入已排序数组中的索引
  • _.sortedUniq - 唯一。对已排序的数组过滤重复值
  • _.take - 切片(从左提取 n 个元素)
  • _.union - 并集
  • _.uniq - 唯一(用于去重)
  • _.zip - 压缩[1, 2], [10, 20], [100, 200] -> [[1, 10, 100], [2, 20, 200]]
  • _.unzip 系列 - 类似 _.zip。[[1, 2], [10, 20], [100, 200]] -> [[1, 10, 100], [2, 20, 200]]
  • _.without - 缺乏。可用 array.filter 替代。
  • _.xor 系列 - X集。只存在于某个数组中的值。

数组 api 详细

_.chunk

_.chunk - 分块。

// _.chunk(array, [size=1]) - 将数组(array)拆分成多个 size 长度的区块,并将这些区块组成一个新数组。 如果array 无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。
{
r = _.chunk(['a', 'b', 'c', 'd'], 2)
// => [['a', 'b'], ['c', 'd']]
l(r) r = _.chunk(['a', 'b', 'c', 'd'], 3)
// => [['a', 'b', 'c'], ['d']]
l(r)
}

_.compact

_.compact - 压紧。可用 array.filter 实现

// _.compact(array) - 创建一个新数组,包含原数组中所有的非假值元素。例如false, null,0, "", undefined, 和 NaN 都是被认为是“假值”。
{
// 返回过滤掉假值的新数组
// 例如 false, null, 0, "", undefined, NaN 都是被认为是“假值”
r = _.compact([false, null, 0, "", undefined, NaN, 1]);
// => [1]
l(r) // 可用 array.filter 实现
r = [false, null, 0, "", undefined, NaN, 1].filter(v => !!(v))
// => [1]
l(r)
}

_.difference 系列

_.difference系列 - 差(从第一个数组中排除给定数组中的值)。_.differenceBy_.differenceWith都是加强版。

// _.difference(array, [values]) - 创建一个具有唯一array值的数组,每个值不包含在其他给定的数组中
// _.differenceBy(array, [values], [iteratee=_.identity]) - 这个方法类似_.difference ,除了它接受一个 iteratee (注:迭代器), 调用array 和 values 中的每个元素以产生比较的标准。
// _.differenceWith(array, [values], [comparator]) - 这个方法类似_.difference ,除了它接受一个 comparator (注:比较器),它调用比较array,values中的元素。 结果值是从第一数组中选择
{ // 从第一个数组中排除给定数组中的值。
// 注:非数组会忽略
r = _.difference([1, 2, 3, 4, 5, 6], [1, 2], [3], [4], 5, [6])
// 5
l(r) // 与 difference 类似。不同之处是每个值得调用 Math.floor 在比较,比如 2.2 和 2.5 认为是相等的
r = _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
// => [3.1, 1.3]
l(r) // The `_.property` iteratee shorthand.
r = _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
// => [{ 'x': 2 }]
l(r) var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
// 与 difference 类似。不同之处是每个值得调用 _.isEqual 这个比较器
// 与 differenceBy 区别,感觉前者是迭代每个值并从中取得值进行比较,而 differenceWith 直接用比较器直接比较
r = _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
// => [{ 'x': 2, 'y': 1 }]
l(r)
}

_.drop 系列

_.drop系列 - 减小(例如去除数组前面两个元素)。某些场景可以使用 ... 结构语法替换;_.dropRightWhile_.dropWhile 都是增强版。

// _.drop(array, [n=1]) - 创建一个切片数组,去除array前面的n个元素。(n默认值为1。)
// _.dropRight(array, [n=1]) - 创建一个切片数组,去除array尾部的n个元素。(n默认值为1。)
// _.dropRightWhile(array, [predicate=_.identity]) - 创建一个切片数组,去除array中从 predicate 返回假值开始到尾部的部分
// _.dropWhile(array, [predicate=_.identity]) - 创建一个切片数组,去除array中从起点开始到 predicate 返回假值结束部分
{
// 去除前面两个元素
r = _.drop([1, 2, 3], 2);
// => [3]
l(r); // 用...解构语法替代上面例子
[, , ...r] = [4, 5, 6]
// => [6]
l(r) // 去除后面两个元素
r = _.dropRight([1, 2, 3], 2);
// => [1]
l(r) // 作用难以理解。直接用 filter
var users = [
{ 'user': 'barney', 'active': true },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': false }
]; r = _.dropRightWhile(users, function (o) { return !o.active; });
// => [{ 'user': 'barney', 'active': true }]
l(r)
}

_.fromPairs & _.toPair

_.fromPairs & _.toPair - 一双。前者可用 array.reduce 实现,后者可用 Object.entries 方便的替代。

// _.fromPairs(pairs) - 与_.toPairs正好相反;这个方法返回一个由键值对pairs构成的对象。
{
let arr = [['fred', 30], ['barney', 40]]
r = _.fromPairs(arr);
// => { 'fred': 30, 'barney': 40 }
l(r) // 用 reduce 重写上述例子
r = arr.reduce((obj, [key, value]) => {
obj[key] = value
return obj
}, {})
// => {fred: 30, barney: 40}
l(r) r = _.toPairs(r)
// => [['fred', 30], ['barney', 40]]
l(r) // 用 Object.entries() 重写上一个示例
r = { fred: 30, barney: 40 }
// Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组
r = Object.entries(r)
// => [['fred', 30], ['barney', 40]]
l(r)
}

_.intersection 系列

_.intersection - 交集。_.intersectionBy_.intersectionWith 是增强版。

// _.intersection([arrays]) - 数组的交集
// _.intersectionBy([arrays], [iteratee=_.identity]) - 这个方法类似_.intersection,区别是它接受一个 iteratee 调用每一个arrays的每个值以产生一个值,通过产生的值进行了比较
// _.intersectionWith([arrays], [comparator]) - 这个方法类似_.intersection,区别是它接受一个 comparator 调用比较arrays中的元素。结果值是从第一数组中选择
{
r = _.intersection([1, 2], [2, 3], [2, 3, 4]);
// => [2]
l(r) r = _.intersection([1, 2], [3, 4]);
// => []
l(r) r = _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
// => [2.1]
l(r) const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
const others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; r = _.intersectionWith(objects, others, _.isEqual);
// => [{ 'x': 1, 'y': 2 }]
l(r)
}

_.pull 系列

_.pull - 移除数组中的值。_.pullAt 根据索引移除,_.pullAll 系列都是加强版。某些场景可使用 array.filter 替代。

// _.pull(array, [values]) - 移除数组array中所有和给定值相等的元素,使用SameValueZero 进行全等比较
// _.pullAll(array, values) - 这个方法类似_.pull,区别是这个方法接收一个要移除值的数组。
// _.pullAllBy(array, values, [iteratee=_.identity]) - 这个方法类似于_.pullAll ,区别是这个方法接受一个 iteratee(迭代函数) 调用 array 和 values的每个值以产生一个值,通过产生的值进行了比较。
// _.pullAllWith(array, values, [comparator]) - 这个方法类似于_.pullAll,区别是这个方法接受 comparator 调用array中的元素和values比较。
// _.pullAt(array, [indexes]) - 根据索引 indexes,移除array中对应的元素,并返回被移除元素的数组。Tip:删除非连续的多个则不方便用 array.splice 替代
{
r = [1, 2, 3, 1, 2, 3]
_.pull(r, 2, 3);
l(r)
// => [1, 1] // 用 array.filter 重写上一个示例
r = [1, 2, 3, 1, 2, 3];
r = r.filter(item => item !== 2 && item !== 3)
// => [1, 1]
l(r) // 数组中移除 { 'x': 3, 'y': 4 }
r = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
_.pullAllWith(r, [{ 'x': 3, 'y': 4 }], _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
l(r) // 移除索引 1 和 3。
r = [5, 10, 15, 20];
_.pullAt(r, 1, 3);
// => [5, 15]
l(r)
}

_.sortedIndex 系列

_.sortedIndex - value 应插入已排序数组中的索引。 _.sortedIndexBy 是增强版。_.sortedIndexOf[鸡肋] 和 array.indexOf 类似。

:数组要已排序,否则得不到预期值。

// _.sortedIndex(array, value) - 使用二进制的方式检索来决定 value值 应该插入到数组中 尽可能小的索引位置,以保证array的排序。
// _.sortedIndexOf(array, value) - 这个方法类似_.indexOf,除了它是在已经排序的数组array上执行二进制检索。
// _.sortedLastIndexOf(array, value) - 这个方法类似_.lastIndexOf
// _.sortedIndexBy(array, value, [iteratee=_.identity]) - 这个方法类似_.sortedIndex
// _.sortedLastIndex(array, value) - 此方法类似于_.sortedIndex
// _.sortedLastIndexBy(array, value, [iteratee=_.identity]) - 这个方法类似_.sortedLastIndex
{
// 数组有序,40 所放索引正确
r = _.sortedIndex([20, 30, 50], 40)
// => 2
l(r) // 数组无序,笔者自己都不知道 40 应放哪里
r = _.sortedIndex([50, 20, 30], 40)
// => 3
l(r) r = [{ 'x': 4 }, { 'x': 5 }];
r = _.sortedIndexBy(r, { 'x': 4.5 }, function (o) { return o.x; });
// => 1
l(r) // 和 array.indexOf 类似
r = _.sortedIndexOf([4, 5, 5, 5, 6], 5);
// => 1
l(r) r = [4, 5, 5, 5, 6].indexOf(5)
// => 1
l(r) // _.sortedLastIndex(array, value) - 和 array.lastIndexOf() 类似
}

_.sortedUniq 系列

_.sortedUniq - 唯一。对已排序的数组过滤重复值,可用 Set 过滤。_.sortedUniqBy 是增强版

// _.sortedUniq(array) - 这个方法类似_.uniq,除了它会优化排序数组。
// _.sortedUniqBy(array, [iteratee]) - 这个方法类似_.uniqBy,除了它会优化排序数组。
{
r = _.sortedUniq([1, 1, 2]);
// => [1, 2]
l(r) // 用 Set 过滤重复值
r = [...new Set([1, 1, 2])]
// => [1, 2]
l(r) r = _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
// => [1.1, 2.3]
l(r) // 利用一个临时数组实现上一个示例
r = [1.1, 1.2, 2.3, 2.4]
const tmp = []
r = r.filter(item => {
let v = Math.floor(item)
if (tmp.includes(v)) {
return false
}
tmp.push(v)
return true
})
// => [1.1, 2.3]
l(r)
}

_.take 系列

_.take - 切片(从左提取 n 个元素)。_.take 和 _.takeRight 可用 array.slice 替代。 _.takeWhile 是增强版。

// _.take(array, [n=1]) - 创建一个数组切片,从array数组的起始元素开始提取n个元素。
// _.takeRight(array, [n=1]) - 创建一个数组切片,从array数组的最后一个元素开始提取n个元素。
// _.takeWhile(array, [predicate=_.identity]) - 与 _.takeRightWhile 类似,只是方向不同
// _.takeRightWhile(array, [predicate=_.identity]) - 从array数组的最后一个元素开始提取元素,直到 predicate 返回假值
{
r = _.take([1, 2, 3], 2);
// => [1, 2]
l(r) // 可用 array.slice 重写上一个示例
r = [1, 2, 3].slice(0, 2)
// => [1, 2]
l(r) r = _.takeRight([1, 2, 3, 4], 2);
// => [3, 4]
l(r) // 可用 array.slice 重写上一个示例
r = [1, 2, 3, 4].slice(-2)
// => [3, 4]
l(r) const users = [
{ 'user': 'barney', 'active': true },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': false }
];
r = _.takeRightWhile(users, function (o) { return !o.active; });
// => objects for ['fred', 'pebbles']
l(r) // 自己实现 _.takeRightWhile
r = []
users.reverse().forEach(item => {
if (item.active) {
return false
}
r.push(item)
})
r.reverse()
// => objects for ['fred', 'pebbles']
l(r)
}

_.union 系列

_.union - 并集。_.union 可用 Set 方便实现。_.unionBy_.unionWith 是增强版。

// _.union([arrays]) - 创建一个按顺序排列的唯一值的数组。所有给定数组的元素值使用SameValueZero做等值比较。
// _.unionBy([arrays], [iteratee=_.identity]) - 这个方法类似_.union ,除了它接受一个 iteratee (迭代函数),调用每一个数组(array)的每个元素以产生唯一性计算的标准
// _.unionWith([arrays], [comparator]) - 这个方法类似_.union, 除了它接受一个 comparator 调用比较arrays数组的每一个元素。例如比较对象
{
r = _.union([1, 3, 5, 7, 3], [6, 4, 3]);
// => [1, 3, 5, 7, 6, 4]
l(r) // 两个数组也可以用 Set 实现
r = [...new Set([...[1, 3, 5, 7, 3], ...[6, 4, 3]])]
// or r = Array.from(new Set([...[1, 3, 5, 7], ...[6, 4, 3]]))
// => [1, 3, 5, 7, 6, 4]
l(r) // 比较处理后的值
r = _.unionBy([2.1], [1.2, 2.3], Math.floor)
// => [2.1, 1.2]
l(r) // 比较对象。对象的唯一性
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
const others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; r = _.unionWith(objects, others, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
l(r)
}

_.uniq 系列

_.uniq - 唯一(用于去重)。_.uniq 可用 Set 方便实现。_.uniqBy _.uniqWith 是增强版。

// _.uniq(array) - 创建一个去重后的array数组副本。
// _.uniqBy(array, [iteratee=_.identity]) - 这个方法类似_.uniq ,除了它接受一个 iteratee (迭代函数),调用每一个数组(array)的每个元素以产生唯一性计算的标准
// _.uniqWith(array, [comparator]) - 这个方法类似_.uniq, 除了它接受一个 comparator 调用比较arrays数组的每一个元素。例如比较对象
{
r = _.uniq([2, 1, 2]);
// => [2, 1]
l(r) r = [...new Set([2, 1, 2])]
// => [2, 1]
l(r) // 比较处理后的值
r = _.uniqBy([2.1, 1.2, 2.3], Math.floor);
// => [2.1, 1.2]
l(r) // 比较对象
r = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; r = _.uniqWith(r, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
l(r)
}

_.zip 系列

_.zip - 压缩。_.zipWith_.zipObject_.zipObjectDeep都是增强版

// _.zip([arrays]) - 创建一个分组元素的数组,数组的第一个元素包含所有给定数组的第一个元素,数组的第二个元素包含所有给定数组的第二个元素,以此类推。
// _.zipWith([arrays], [iteratee=_.identity]) - 这个方法类似于_.zip,不同之处在于它接受一个 iteratee(迭代函数),来指定分组的值应该如何被组合。
// _.zipObject([props=[]], [values=[]]) - 这个方法类似_.fromPairs,除了它接受2个数组,第一个数组中的值作为属性标识符(属性名),第二个数组中的值作为相应的属性值。
// _.zipObjectDeep([props=[]], [values=[]])- 这个方法类似_.zipObject,除了它支持属性路径。
{
r = _.zip([1, 2], [10, 20], [100, 200])
// => [[1, 10, 100], [2, 20, 200]]
l(r) // 自己实现一个弱版本
const zip = (...arrs) => {
const result = []
arrs[0].forEach((v, index) => {
const tmp = []
arrs.forEach(item => tmp.push(item[index]))
result.push(tmp)
})
return result
} r = zip([1, 2], [10, 20], [100, 200])
// => [[1, 10, 100], [2, 20, 200]]
l(r) r = _.zipWith([1, 2], [10, 20], [100, 200], function (a, b, c) {
return a + b + c;
});
// => [111, 222]
l(r) // 组合成对象
r = _.zipObject(['a', 'b'], [1, 2]);
// => { 'a': 1, 'b': 2 }
l(r) r = _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2])
// => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
l(r)
}

_.unzip 系列

_.unzip - 解压。似于_.zip。_.unzipWith 是增强版。

// _.unzip(array) - 这个方法类似于_.zip,除了它接收分组元素的数组,并且创建一个数组,分组元素到打包前的结构。(:返回数组的第一个元素包含所有的输入数组的第一元素,第一个元素包含了所有的输入数组的第二元素,依此类推。)
// _.unzipWith(array, [iteratee=_.identity]) - 此方法类似于_.unzip,除了它接受一个iteratee指定重组值应该如何被组合。增强版
{
r = _.unzip([1, 2], [10, 20], [100, 200])
// => []
l(r)
// 用数组包裹后,就和 _.zip 效果相同
r = _.unzip([[1, 2], [10, 20], [100, 200]])
// => [[1, 10, 100], [2, 20, 200]]
l(r) r = _.unzipWith([[1, 10, 100], [2, 20, 200]], _.add);
// => [3, 30, 300]
l(r)
}

_.without

_.without - 缺乏。可用 array.filter 替代

// _.without(array, [values]) - 创建一个剔除所有给定值的新数组。
{
r = _.without([2, 1, 2, 3], 1, 2);
// => [3]
l(r) r = [2, 1, 2, 3].filter(item => ![1, 2].includes(item))
// => [3]
l(r)
}

_.xor 系列

_.xor - X集(只存在于某个数组中的值)。_.xorBy_.xorWith 是增强版

// _.xor([arrays]) - 创建一个给定数组唯一值的数组,使用symmetric difference做等值比较。返回值的顺序取决于他们数组的出现顺序。每个元素的差集,即只存在于某个数组中的值,其他数组没有改值。
// _.xorBy([arrays], [iteratee=_.identity]) - 这个方法类似_.xor ,除了它接受 iteratee(迭代器),这个迭代器 调用每一个 arrays(数组)的每一个值,以生成比较的新值。增强版
// _.xorWith([arrays], [comparator]) - 该方法是像_.xor,除了它接受一个 comparator ,以调用比较数组的元素。增强版
{
r = _.xor([1, 2], [3, 2], [4, 2], [5])
// => [1, 3, 4, 5]
l(r)
r = _.xor([1, 2], [3, 2], [4, 2, 5], [5])
// => [1, 3, 4]
l(r) // 转换后的值比较
r = _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
// => [1.2, 3.4]
l(r) // 对象比较
const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
const others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
r = _.xorWith(objects, others, _.isEqual);
// => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
l(r)
}

鸡肋

_.concat

_.concat - 连接数组。与 array.concat 效果相同,也可用 es6+ 语法 ... 实现

// _.concat(array, [values]) - 创建一个新数组,将array与任何数组 或 值连接在一起。
//
{
const array = [1];
r = _.concat(array, 2, [3], [[4]]); console.log(r);
// => [1, 2, 3, [4]] // 与原生数组的 concat 效果相同
r = array.concat(2, [3], [[4]])
// => [1, 2, 3, [4]]
l(r) r = [...array, 2, ...[3], ...[[4]]]
// [1, 2, 3, [4]]
l(r)
}
_.fill

_.fill - 填充。可用 array.fill 替代

// _.fill(array, value, [start=0], [end=array.length]) - 使用 value 值来填充(替换) array,从start位置开始, 到end位置结束(但不包含end位置)。
{ let array = [1, 2, 3];
r = [...array]
_.fill(r, 'a');
l(r)
// => ['a', 'a', 'a'] // array.fill 重写上一个示例
// fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
r = [...array]
r.fill('b')
l(r)
// => ['b', 'b', 'b'] r = [4, 6, 8, 10]
_.fill(r, '*', 1, 3)
l(r)
// => [4, '*', '*', 10] // array.fill 重写上一个示例
r = [4, 6, 8, 10]
r.fill('*', 1, 3)
l(r)
// => [4, '*', '*', 10]
}
_.findIndex

_.findIndex - 可用 Array.prototype.findIndex 替代

// _.findIndex(array, [predicate=_.identity], [fromIndex=0]) - 该方法类似_.find,区别是该方法返回第一个通过 predicate 判断为真值的元素的索引值(index),而不是元素本身。
// _.findLastIndex(array, [predicate=_.identity], [fromIndex=array.length-1])
{
let users = [
{ 'user': 'fred', 'active': false },
{ 'user': 'fred', 'active': true },
{ 'user': 'pebbles', 'active': true }
]; r = _.findIndex(users, function (o) { return o.user == 'fred' && o.active === false });
// => 0
l(r) // array.findIndex 重写上一个示例
// findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1。
r = users.findIndex(o => o.user == 'fred' && o.active === false)
// => 0
l(r) // The `_.matches` iteratee shorthand.
r = _.findIndex(users, { 'user': 'fred', 'active': true });
// => 1
l(r)
}
_.head

_.head - 可用 arr[index] 或 att.at(index) 替代

// _.head(array) - 获取数组 array 的第一个元素。可用 arr[index] 或 att.at(index) 替代。
{
const arr = [2, 3, 4]
r = _.head(arr)
// => 2
l(r) // 需要 chrome 92+
// r = arr.at(0)
// => 2
// l(r)
}
_.flatten

_.flatten - 变平。array.flat 能非常方便的替代这3个api。

// _.flatten(array) - 减少一级array嵌套深度。
// _.flattenDeep(array) - 将array递归为一维数组。
// _.flattenDepth(array, [depth=1]) - 根据 depth 递归减少 array 的嵌套层级
{
let arr = [1, [2, [3, [4]], 5]]
r = _.flatten(arr);
// => [1, 2, [3, [4]], 5]
l(r) // array.flat 重写上一个示例
r = arr.flat()
// => [1, 2, [3, [4]], 5]
l(r) r = _.flattenDeep(arr)
// => [1, 2, 3, 4, 5]
l(r) // 用 array.flat 重写上一个示例
r = arr.flat(Infinity)
// => [1, 2, 3, 4, 5]
l(r)
}
_.remove

_.remove - 删除。可用 array.filter 替代。

// _.remove(array, [predicate=_.identity]) - 移除数组中predicate(断言)返回为真值的所有元素,并返回移除元素组成的数组
{
let array = [1, 2, 3, 4];
r = _.remove(array, function (n) {
return n % 2 == 0;
}); // => [2, 4]
l(r) // 用 array.filter 替代
r = [1, 2, 3, 4]
r = r.filter(item => item % 2 === 0)
// => [2, 4]
l(r)
}
_.tail

_.tail - 尾部。可用 array.slice 替代

// _.tail(array) - 获取除了array数组第一个元素以外的全部元素。
{
r = _.tail([1, 2, 3]);
// => [2, 3]
l(r) r = [1, 2, 3].slice(1)
// => [2, 3]
l(r)
}
其他
  • _.initial(array) - 获取数组array中除了最后一个元素之外的所有元素。名字不好记。可用 [1, 2, 3].slice(0, -1) 替代 或 let [, ...r] = [1,2,3].reverse(); r.reverse()

  • _.join(array, [separator=',']) - 可用 Array.prototype.join 替代

  • _.last(array) - 获取array中的最后一个元素。 可用 array[array.length - 1] 替代

  • _.lastIndexOf(array, value, [fromIndex=array.length-1]) - 可用 Array.prototype.lastIndexOf 替代

  • _.nth(array, [n=0]) - 获取array数组的第n个元素。直接用数组索引获取 或 Array.prototype.at 替代

  • _.reverse(array) - 逆序。可用 array.reverse 替代。

  • _.slice(array, [start=0], [end=array.length]) - slice。可用 array.slice 替代

  • _.indexOf - 可用 Array.prototype.indexOf 替代

陪你去看 Lodash.js 起步的更多相关文章

  1. 从源码的角度看 React JS 中批量更新 State 的策略(下)

    这篇文章我们继续从源码的角度学习 React JS 中的批量更新 State 的策略,供我们继续深入学习研究 React 之用. 前置文章列表 深入理解 React JS 中的 setState 从源 ...

  2. 从源码的角度看 React JS 中批量更新 State 的策略(上)

    在之前的文章「深入理解 React JS 中的 setState」与 「从源码的角度再看 React JS 中的 setState」 中,我们分别看到了 React JS 中 setState 的异步 ...

  3. h5 plus/h5+规范使用,模块索引,教你如何去看h5+的手册

    最近看了下h5+规范的官网,开始觉得晦涩难懂,确实很乱,不过这也是基于我不理解的情况,终于艰难读完了,现在来分享下心得吧,基本看完文章,按我的方法,应该可以直接上手项目. 我准备的工具 hbuilde ...

  4. 一篇文章看懂JS闭包,都要2020年了,你怎么能还不懂闭包?

     壹 ❀ 引 我觉得每一位JavaScript工作者都无法避免与闭包打交道,就算在实际开发中不使用但面试中被问及也是常态了.就我而言对于闭包的理解仅止步于一些概念,看到相关代码我知道这是个闭包,但闭包 ...

  5. 擦亮自己的眼睛去看SQLServer之简单Insert(转)

    摘要:本来是打算先写SQLServer历史的,不过感觉写那部分内容比较难还需要多查些资料.于是调整了下顺序写下简单的Insert语句. 不过感觉写那部分内容比较难还需要多查些资料.于是调整了下顺序写下 ...

  6. 我追一个处女座的女孩快两个月了,我之前聊得很好,她说过有空call我去看电影,过了一个月她就不理我了,我喜欢她, 我是程序员,百度发不了那么多字。

    她刚刚进公司的时候,公司组织去打球,我叫她一起去她也去了,我和她聊了很多,聊得很自然,很开心,如我是哪个学习毕业的 我出来工作多久了等,她也聊了 她自己好多,她现在在读大学,只有周日上一天课那种. 我 ...

  7. lodash (js实用工具库)

    是什么? 它提供了一整套函数式编程的实用功能, 并且支持模块化, 比underscore更优秀. 文档? http://lodashjs.com/docs/ 引用? <script src=&q ...

  8. Lodash.js常用拷贝

    lodash.js 降低 array.number.objects.string 等等的使用难度从而让 JavaScript 变得更简单.非常适用于:遍历 array.object 和 string: ...

  9. Codevs 1570 去看电影

    1570 去看电影  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 农夫约翰带着他的一些奶牛去看 ...

随机推荐

  1. 「学习笔记」倍增思想与lca

    目录 ST表 算法 预处理 查询 关于 log2 Code 预处理 查询 例题 P2880 P2048 lca 树上 RMQ 前置知识:欧拉序列 算法 Code 离线 Tarjan 算法 Code 倍 ...

  2. 详谈 MySQL 8.0 原子 DDL 原理

    柯煜昌 青云科技研发顾问级工程师 目前从事 RadonDB 容器化研发,华中科技大学研究生毕业,有多年的数据库内核开发经验. 文章字数 3800+,阅读时间 15 分钟 背景 MySQL 5.7 的字 ...

  3. Python 第二次实验

    [1] (程序设计)三位水仙花数的计算."三位水仙花数"是指一个三位整数,其各位数字的3次方和等于该数本身.例如:ABC是一个"3位水仙花数",则:A的3次方+ ...

  4. jenkins流水线部署springboot应用到k8s集群(k3s+jenkins+gitee+maven+docker)(2)

    前言:上篇已介绍了jenkins在k3s环境部署,本篇继续上篇讲述流水线构建部署流程 1.从gitlab上拉取代码步骤 在jenkins中,新建一个凭证:Manage Jenkins -> Ma ...

  5. 助力培养高质量AI人才,璞公英乐学平台在日本深受好评!

    璞公英乐学平台(原名"璞睿魔数")自进入日本市场以来,受到日本用户的广泛好评.近日,日本AI门户网站AIsmiley在发刊的杂志<AI人才育成指南>中对璞公英乐学平台做 ...

  6. Exchange备份和日志清除

    最近新部署Exchange 2019,虽然变化不大,但是也遇到了一些小问题.随着深入研究,就能发现一些以前被忽视的点.Exchange完成备份后,数据库日志并没有被清除,依然存在.https://ww ...

  7. Svelte Ui Admin后台管理系统|svelte3+svelteUI中后台前端解决方案

    基于svelte3.x+svelteKit+svelte-ui网页后台管理系统SvelteAdmin. Svelte-Ui-Admin 基于svelte3.x+svelteKit+vite3+echa ...

  8. 在Ubuntu上安装Odoo时遇到的问题

    这两天开始看<Odoo快速入门与实践  Python开发ERP指南>(刘金亮 2019年5月第1版 机械工业出版社).试着在Ubuntu上安装Odoo,遇到很多问题,通过在网上查找,都已解 ...

  9. ES配置生成SSL使用的证书

    cd /usr/local/elasticsearch/bin/ ./elasticsearch-certgen ##################################### Pleas ...

  10. java基础之常用类1

    java基础 以下内容为本人的学习笔记,如需要转载,请声明原文链接   java常用类: 1.内部类 2.Object类 3.Object类常用方法 4.包装类 5.String类 6.BigDeci ...