Lodash 提供模块化、性能和额外功能的现代 JavaScript 实用工具库。它通过降低 Array、Number、Objects、String 等等的使用难度从而让 JavaScript 变得更简单,提高开发者效率。类似的还有 Underscore 和 Lazy,还有一个 Ramda 库,它是用柯里化实现的。
支持情况:Chrome 74-75,Firefox 66-67,IE 11,Edge 18,Safari 11-12 & Node.js 8-12
CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
NPM:
npm i lodash
以下将介绍 Loadsh 的常用方法
_.filter
返回一个新的过滤后的数组。
var users = [
{ user: 'barney', age: 36, active: true },
{ user: 'fred', age: 40, active: false }
]
_.filter(users, (o) => !o.active) // { 'user': 'fred', 'age': 40, 'active': false }
_.filter(users, { age: 36, active: true }) // { 'user': 'barney', 'age': 36, 'active': true },
_.filter(users, ['active', false]) // { 'user': 'fred', 'age': 40, 'active': false }
_.filter(users, 'active') // { 'user': 'barney', 'age': 36, 'active': true }
_.find
和 _.findLast
返回匹配元素,否则返回 undefined
。
var users = [
{ user: 'barney', age: 36, active: true },
{ user: 'fred', age: 40, active: false },
{ user: 'pebbles', age: 1, active: true }
]
_.find(users, (o) => o.age < 40) // { 'user': 'barney', 'age': 36, 'active': true }
_.find(users, { age: 1, active: true }) // { 'user': 'pebbles', 'age': 1, 'active': true }
_.find(users, ['active', false]) // { 'user': 'fred', 'age': 40, 'active': false }
_.find(users, 'active') // { 'user': 'barney', 'age': 36, 'active': true }
_.findLast([1, 2, 3, 4], (n) => n % 2 == 1) // 3
它们都适用于数组和对象。
_.set
返回 object
。设置 object
对象中对应 path
属性路径上的值,如果path
不存在,则创建。 缺少的索引属性会创建为数组,而缺少的属性会创建为对象。 使用_.setWith
定制path
创建。
let object = { a: [{ b: { c: 3 } }] }
_.set(object, 'a[0].b.c', 4)
console.log(object.a[0].b.c) // 4
_.set(object, ['x', '0', 'y', 'z'], 5)
console.log(object.x[0].y.z) // 5
_.get
返回解析的值。根据 object
对象的 path
路径获取值。 如果解析 value 是 undefined
会以 defaultValue
取代。
let object = { a: [{ b: { c: 3 } }] }
_.get(object, 'a[0].b.c') // 3
_.get(object, ['a', '0', 'b', 'c']) // 3
_.get(object, 'a.b.c', 'default') // 'default'
_.forEach
和 _.forEachRight
返回集合 collection
。
_([1, 2]).forEach(function (value) {
console.log(value) // 1 2
})
_.forEach({ a: 1, b: 2 }, (value, key) => {
console.log(key) // a b (不保证迭代顺序)
})
_.forEachRight([1, 2], function (value) {
console.log(value) // 2 1.
})
_.map
返回新的映射后数组。
function square(n) {
return n * n
}
_.map([4, 8], square) // [16, 64]
_.map({ a: 4, b: 8 }, square) // [16, 64] (不保证迭代顺序)
var users = [{ user: 'barney' }, { user: 'fred' }]
_.map(users, 'user') // ['barney', 'fred']
_.every
如果所有元素经 predicate(断言函数) 检查后都都返回真值,那么就返回true
,否则返回 false
。
_.every([true, 1, null, 'yes'], Boolean) // false
let users = [
{ user: 'barney', age: 36, active: false },
{ user: 'fred', age: 40, active: false }
]
_.every(users, { user: 'barney', active: false }) // false
_.every(users, ['active', false]) // true
_.every(users, 'active') // false
_.chunk
返回一个包含拆分区块的新数组(注:相当于一个二维数组)。
_.chunk(['a', 'b', 'c', 'd'], 2) // [['a', 'b'], ['c', 'd']]
_.compact
返回过滤掉假值的新数组。
_.compact([0, 1, false, 2, '', 3]) // [1, 2, 3]
_.fill
返回 array
。使用 value
值来填充(替换) array
,从start
位置开始, 到end
位置结束(但不包含end
位置)。
_.fill([1, 2, 3], 'a') // ['a', 'a', 'a']
_.fill(Array(4), 'x') // [ 'x', 'x', 'x', 'x' ]
_.fill([4, 6, 8, 10], '*', 1, 3) // [4, '*', '*', 10]
_.flattenDeep([1, [2, [3, [4]], 5]]) // [1, 2, 3, 4, 5]
_.flatten
返回减少嵌套层级后的新数组。
_.flatten([1, [2, [3, [4]], 5]]) // [1, 2, [3, [4]], 5]
_.flattenDeep
返回一个的新一维数组。
_.flattenDeep([1, [2, [3, [4]], 5]]) // [1, 2, 3, 4, 5]
_.drop
返回 array
剩余切片。
_.drop([1, 2, 3]) // [2, 3]
_.drop([1, 2, 3], 2) // [3]
_.drop([1, 2, 3], 5) // []
_.drop([1, 2, 3], 0) // [1, 2, 3]
_.dropRight([1, 2, 3]) // [1, 2]
_.take
返回array
数组的切片(从起始元素开始n
个元素)。_.takeRight
返回array
数组的切片(从结尾元素开始n
个元素)。
_.take([1, 2, 3]) // [1]
_.take([1, 2, 3], 2) // [1, 2]
_.take([1, 2, 3], 5) // [1, 2, 3]
_.take([1, 2, 3], 0) // []
_.takeRight([1, 2, 3], 2) // [2, 3]
_.slice
返回 数组 array
裁剪部分的新数组。
_.slice([1, 2, 3], 0, 2) // [1, 2]
_.initial
返回截取后的数组array
_.initial([1, 2, 3]) // [1, 2]
_.rest
返回新的函数。
let say = _.rest(function (what, names) {
return (
what +
' ' +
_.initial(names).join(', ') +
(_.size(names) > 1 ? ', & ' : '') +
_.last(names)
)
})
say('hello', 'fred', 'barney', 'pebbles') // 'hello fred, barney, & pebbles'
_.dropWhile
返回 array
剩余切片。
_.dropWhile(list, 'active') // 像过滤器一样工作
_.dropWhile(list, 'active', true)
_.dropWhile(list, { active: true })
_.dropWhile(list, (n) => ...)
_.dropRightWhile(list, ...)
let users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
]
_.dropWhile(users, (o) => !o.active) // { 'user': 'pebbles', 'active': true }
_.dropWhile(users, { 'user': 'barney', 'active': false }) // [{ 'user': 'barney', 'active': false }, {...}]
_.dropWhile(users, ['active', false]) // { 'user': 'pebbles', 'active': true }
_.dropWhile(users, 'active') // [{user: "barney", active: false}, {...}, {...}]
_.without
返回过滤值后的新数组。
_.without([2, 1, 2, 3], 1, 2) // [3]
_.remove
返回移除元素组成的新数组。
let array = [1, 2, 3, 4]
let evens = _.remove(array, (n) => {
return n % 2 == 0
})
console.log(array) // [1, 3]
console.log(evens) // [2, 4]
_.first
返回数组 array
的第一个元素。
_.head([1, 2, 3]) // 1
_.head([]) // undefined
_.last
返回 array
中的最后一个元素
_.last([1, 2, 3]) // 3
_.at
返回选中值的数组。
_.at([1, 2, 3], 0) // [1]
_.at([1, 2, 3], [0, 1]) // [1, 2]
let object = { a: [{ b: { c: 3 } }, 4] }
_.at(object, ['a[0].b.c', 'a[1]']) // [3, 4]
_.uniq
返回新的去重后的数组。
_.uniq([2, 1, 2]) // [2, 1]
_.difference
返回一个过滤值后的新数组。
_.difference([3, 2, 1], [4, 2]) // [3, 1]
_.intersection
返回一个包含所有传入数组交集元素的新数组。
_.intersection([2, 1], [4, 2], [1, 2]) // [2]
_.union
返回一个新的联合数组。
_.union([2], [1, 2]) // [2, 1]
_.concat
返回连接后的新数组。
let array = [1]
let other = _.concat(array, 2, [3], [[4]])
console.log(other) // [1, 2, 3, [4]]
console.log(array) // [1]
_.findIndex
和 _.findLastIndex
返回找到元素的索引值(index),否则返回 -1
。
let users = [
{ user: 'barney', active: false },
{ user: 'fred', active: false },
{ user: 'pebbles', active: true }
]
_.findIndex(list, fn)
_.findLastIndex(list, fn)
_.findIndex(users, (o) => o.user == 'barney') // 0
_.findIndex(users, { user: 'fred', active: false }) // 1
_.findIndex(users, ['active', false]) // 0
_.findIndex(users, 'active') // 2
_.findLastIndex(users, (o) => o.user == 'pebbles') // 2
_.sortedIndex
和 _.sortedLastIndex
返回 value
值应该在数组 array
中插入的索引位置 index。
_.sortedIndex([30, 50], 40) // 1
_.sortedLastIndex([4, 5, 5, 5, 6], 5) // 4
_.indexOf
返回值 value
在数组中的索引位置,没有找到为返回-1
。
_.indexOf([1, 2, 1, 2], 2) // 1
_.indexOf([1, 2, 1, 2], 2, 2) // 3
返回预设参数的函数。
let greet = (greeting, name) => `${greeting}, ${name}!`
let fn = _.partial(fn, 'hi')
fn('joe') // 'hi, joe!'
返回新的柯里化(curry)函数。
_.curry(greet)('hi') // function(name)
_.curryRight(greet)('joe') // function(greet)
_.throttle
返回节流的函数。_.debounce
返回防抖的函数。
_.throttle(fn)
_.debounce(fn)
document.addEventListener('click', _.before(5, fn)) // 只能调用5次
document.addEventListener('click', _.after(5, fn)) // 5次后才能调用
const initialize = _.once(fn)
initialize()
initialize() // 类似 _.before(1, fn),只调用一次 fn
_.wrap
返回新的函数。
_.wrap(_.escape, (name) => `hi ${name}`) // 与执行 name = _.escape(name) 相同
_.delay
返回计时器 id 延迟。延迟 wait
毫秒后调用 fn
。 调用时,任何附加的参数会传给 fn
。
_.delay(
(text) => {
console.log(text)
},
2000,
'Hello World!'
)
_.filter
返回一个新的过滤后的数组。
function isEven(n) {
return n % 2 == 0
}
_.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)) // => [1, 3, 5]
_.memoize
返回缓存化后的函数。
_.memoize(fn)
_.memoize(fn, ...)
var object = { 'a': 1, 'b': 2 };
var other = { 'c': 3, 'd': 4 };
var values = _.memoize(_.values)
values(object) // => [1, 2]
values(other) // => [3, 4]
object.a = 2
values(object) // => [1, 2]
// 修改结果缓存。
values.cache.set(object, ['a', 'b'])
values(object) // => ['a', 'b']
// 替换 _.memoize.Cache。
_.memoize.Cache = WeakMap
转换字符串 string
首字母为大写,剩下为小写。
_.capitalize('hello world') // 'Hello world'
转换 string
字符串为 start case。
_.startCase('hello_world') // 'Hello World'
转换字符串 string
为 snake case。
_.snakeCase('hello world') // 'hello_world'
转换字符串 string
为 kebab case。
_.kebabCase('hello world') // 'hello-world'
转换字符串 string
为 驼峰写法。
_.camelCase('hello world') // 'helloWorld'
_.pad
、_.padStart
、_.padEnd
返回填充后的字符串。
_.pad('abc', 3) // 'abc'
_.pad('abc', 8) // ' abc '
_.pad('abc', 8, '_-') // '_-abc_-_'
_.padStart('abc', 3) // 'abc'
_.padStart('abc', 6) // ' abc'
_.padStart('abc', 6, '_-') // '_-_abc'
_.padEnd('abc', 3) // 'abc'
_.padEnd('abc', 6) // 'abc '
_.padEnd('abc', 6, '_-') // 'abc_-_'
从 string
字符串中移除前面和后面的空格或指定的字符。
_.trim(' str ') // 'str'
从 string
字符串中移除后面的空格或指定的字符。
_.trimStart(' str ') // 'str '
从 string
字符串中移除后面的空格或指定的字符。
_.trimEnd(' str ') // ' str'
_.trimEnd('-_-abc-_-', '-_-') // '-_-abc'
_.repeat
重复 N 次给定字符串。
_.repeat('-', 2) // '--'
_.repeat('abc', 2) // 'abcabc'
_.repeat('abc', 0) // ''
转换字符串 string
中拉丁语-1 补充字母和拉丁语扩展字母-A为基本的拉丁字母,并且去除组合变音标记。
_.deburr('déjà vu') // 'deja vu'
截断 string
字符串,如果字符串超出了限定的最大值。 被截断的字符串后面会以 omission 代替,omission 默认是 "..."。
_.truncate('hello world', 5) // 'hello...'
_.truncate('hi-diddly-ho there, neighborino', {
length: 24,
separator: ' '
}) // 'hi-diddly-ho there,...'
_.truncate('hi-diddly-ho there, neighborino', {
length: 24,
separator: /,? +/
}) // 'hi-diddly-ho there...'
_.truncate('hi-diddly-ho there, neighborino', {
omission: ' [...]'
}) // 'hi-diddly-ho there, neig [...]'
检查字符串 string
是否以 target
开头。
_.startsWith('abc', 'a') // true
_.startsWith('abc', 'b') // false
_.startsWith('abc', 'b', 1) // true
检查字符串 string
是否以给定的 target
字符串结尾。
_.endsWith('abc', 'c') // true
_.endsWith('abc', 'b') // false
_.endsWith('abc', 'b', 2) // true
_.keys
返回包含属性名的数组。创建一个 object 的自身可枚举属性名为数组。_.values
返回对象属性的值的数组。创建 object 自身可枚举属性的值为数组。
_.keys(obj)
_.values(obj)
function Foo() {
this.a = 1
this.b = 2
}
Foo.prototype.c = 3
_.keys(new Foo()) // ['a', 'b'] (无法保证遍历的顺序)
_.keys('hi') // ['0', '1']
_.values(new Foo()) // [1, 2] (无法保证遍历的顺序)
_.values('hi') // ['h', 'i']
Loadsh 跟 jQuery 一样支持链式调用
_([1, 2, 3])
.map((n) => n * n)
.tap(console.log)
.thru((n) => n.reverse())
.value()
支持链式调用的方法
不支持链式调用的方法
关于 Ramda 的教程可以查看阮一峰老师的 Ramda 函数库参考教程。
NPM:
npm install ramda
CDN:<script src="https://cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>