简介
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
为什么选择 Lodash ?
Lodash 通过降低 array
、number
、objects
、string
等等的使用难度从而让 JavaScript 变得更简单。 Lodash 的模块化方法非常适用于:
- 遍历
array
、object
和string
- 对值进行操作和检测
- 创建符合功能的函数
数组
- _.chunk(array, [size=1])
将数组(array)拆分成多个size
长度的区块,并将这些区块组成一个新数组。 如果array
无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。
参数
array
(Array): 需要处理的数组
[size=1]
(number): 每个数组区块的长度
返回
(Array): 返回一个包含拆分区块的新数组(注:相当于一个二维数组)。
示例_.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']] _.chunk(['a', 'b', 'c', 'd'], 3); // => [['a', 'b', 'c'], ['d']]
- _.compact(array)
创建一个新数组,包含原数组中所有的非假值元素。例如false
,null
,0
,""
,undefined
, 和NaN
都是被认为是“假值”。
参数
array (Array): 待处理的数组
返回值
(Array): 返回过滤掉假值的新数组。
示例_.compact([0, 1, false, 2, '', 3]); // => [1, 2, 3]
- _.uniq(array)
创建一个去重后的array
数组副本。使用了SameValueZero
做等值比较。只有第一次出现的元素才会被保留。
参数
array
(Array): 要检查的数组。
返回
(Array): 返回新的去重后的数组。
示例_.uniq([2, 1, 2]); // => [2, 1]
- _ .findIndex(array, [predicate=_.identity], [fromIndex=0])
该方法类似_.find
,区别是该方法返回第一个通过predicate
判断为真值的元素的索引值(index),而不是元素本身。
参数
array
(Array): 要搜索的数组。
[predicate=_.identity]
(Array|Function|Object|string): 这个函数会在每一次迭代调用。
[fromIndex=0]
(number): The index to search from.
返回值
(number): 返回找到元素的索引值(index),否则返回-1
。
示例var users = [ { 'user': 'barney', 'active': false }, { 'user': 'fred', 'active': false }, { 'user': 'pebbles', 'active': true } ]; _.findIndex(users, function(o) { return o.user == 'barney'; }); // => 0 // The `_.matches` iteratee shorthand. _.findIndex(users, { 'user': 'fred', 'active': false }); // => 1 // The `_.matchesProperty` iteratee shorthand. _.findIndex(users, ['active', false]); // => 0 // The `_.property` iteratee shorthand. _.findIndex(users, 'active'); // => 2
集合
-
_ .forEach(collection, [iteratee=_.identity])
调用iteratee
遍历collection
(集合) 中的每个元素 -
_ .find(collection, [predicate=_.identity], [fromIndex=0])
遍历collection
(集合)元素,返回predicate
(断言函数)第一个返回真值的第一个元素。 -
_ .filter(collection, [predicate=_.identity])
遍历collection
(集合)元素,返回predicate
(断言函数)返回真值的所有元素的数组。 -
_ .map(collection, [iteratee=_.identity])
创建一个数组, value(值) 是iteratee
(迭代函数)遍历collection
(集合)中的每个元素后返回的结果。 -
_ .groupBy(collection, [iteratee=_.identity])(指定条件对元素进行分组)
创建一个对象,key
是iteratee
遍历collection
(集合) 中的每个元素返回的结果。分组值的顺序是由他们出现在collection
(集合) 中的顺序确定的。每个键对应的值负责生成key
的元素组成的数组。iteratee
调用 1 个参数: (value)。
参数
collection
(Array|Object): 一个用来迭代的集合。
[iteratee=_.identity]
(Array|Function|Object|string): 这个迭代函数用来转换key
。
返回
(Object): 返回一个组成聚合的对象。
示例_.groupBy([6.1, 4.2, 6.3], Math.floor); // => { '4': [4.2], '6': [6.1, 6.3] } // The `_.property` iteratee shorthand. _.groupBy(['one', 'two', 'three'], 'length'); // => { '3': ['one', 'two'], '5': ['three'] }
-
_ .reduce(collection, [iteratee=_.identity], [accumulator])
该方法将collection
缩减为值,该值是通过iteratee
运行collection
中的每个元素的累积结果,其中为每个连续的调用提供了上一个的返回值。如果未指定累加器,则将集合的第一个元素用作初始值。iteratee
调用 4 个参数:(accumulator, value, index|key, collection).
注意 :lodash 中有许多方法是防止作为其他方法的迭代函数(注:即不能作为iteratee
参数传递给其他方法),例如:_.reduce
,_.reduceRight
, 和_.transform
。
受保护的方法有(注:即这些方法不能使用_.reduce
,_.reduceRight
, 和_.transform
作为iteratee
迭代函数参数):
assign
,defaults
,defaultsDeep
,includes
,merge
,orderBy
, 和sortBy
参数
collection
(Array|Object): 用来迭代的集合。
[iteratee=_.identity]
(Function): 每次迭代调用的函数。
[accumulator]
(): 初始值。
返回
(): 返回累加后的值。
示例_.reduce([1, 2], function(sum, n) { return sum + n; }, 0); // => 3 _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { (result[value] || (result[value] = [])).push(key); return result; }, {}); // => { '1': ['a', 'c'], '2': ['b'] } (无法保证遍历的顺序)
-
_ .countBy(collection, [iteratee=_.identity])
统计指定条件的数量。
参数
collection
(Array|Object): 一个用来迭代的集合。
[iteratee=_.identity]
(Array|Function|Object|string): 一个迭代函数,用来转换 key(键)。
返回
(Object): 返回一个组成集合对象。
示例_.countBy([6.1, 4.2, 6.3], Math.floor); // => { '4': 1, '6': 2 } // The `_.property` iteratee shorthand. _.countBy(['one', 'two', 'three'], 'length'); // => { '3': 2, '5': 1 }
-
_ .every(collection, [predicate=_.identity]) (判断集合中是否全部满足指定条件)
通过predicate
(断言函数) 检查collection
(集合)中的所有元素是否都返回真值。一旦predicate
(断言函数)返回假值,迭代就马上停止。predicate
(断言函数)调用三个参数: (value, index|key, collection)。
注意: 这个方法对于对于空集合返回true
,因为空集合的任何元素都是true
。
参数
collection
(Array|Object): 一个用来迭代的集合。
[predicate=_.identity]
(Array|Function|Object|string): 每次迭代调用的函数。
返回
(boolean): 如果所有元素经predicate
(断言函数) 检查后都都返回真值,那么就返回true
,否则返回false
。
示例_.every([true, 1, null, 'yes'], Boolean); // => false var users = [ { 'user': 'barney', 'age': 36, 'active': false }, { 'user': 'fred', 'age': 40, 'active': false } ]; // The `_.matches` iteratee shorthand. _.every(users, { 'user': 'barney', 'active': false }); // => false // The `_.matchesProperty` iteratee shorthand. _.every(users, ['active', false]); // => true // The `_.property` iteratee shorthand. _.every(users, 'active'); // => false
-
_ .orderBy(collection, [iteratees=[_.identity]], [orders])
此方法类似于_.sortBy
,除了它允许指定iteratee
(迭代函数)结果如何排序。 如果没指定orders
(排序),所有值以升序排序。 否则,指定为 “desc
” 降序,或者指定为 “asc
” 升序,排序对应值。
参数
collection
(Array|Object): 用来迭代的集合。
[iteratees=[_.identity]]
(Array[]|Function[]|Object[]|string[]): 排序的迭代函数。
[orders]
(string[]):iteratees
迭代函数的排序顺序。
返回
(Array): 排序排序后的新数组。
示例var users = [ { 'user': 'fred', 'age': 48 }, { 'user': 'barney', 'age': 34 }, { 'user': 'fred', 'age': 40 }, { 'user': 'barney', 'age': 36 } ]; // 以 `user` 升序排序 再 `age` 以降序排序。 _.orderBy(users, ['user', 'age'], ['asc', 'desc']); // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
函数
-
_.debounce(func, [wait=0], [options=])
(防抖动,一般用在改变窗口大小或者滚动条移动时触发比较昂贵的操作时使用,或者浮窗等延迟显示消失时使用)
创建一个debounced
(防抖动)函数,该函数会从上一次被调用后,延迟wait
毫秒后调用func
方法。debounced
(防抖动)函数提供一个cancel
方法取消延迟的函数调用以及flush
方法立即调用。可以提供一个options
(选项) 对象决定如何调用func
方法,options.leading
与|或options.trailing
决定延迟前后如何触发(注:是 先调用后等待 还是 先等待后调用)。func
调用时会传入最后一次提供给debounced
(防抖动)函数的参数。 后续调用的debounced
(防抖动)函数返回是最后一次func
调用的结果。
注意: 如果leading
和trailing
选项为true
, 则func
允许trailing
方式调用的条件为: 在wait
期间多次调用防抖方法。
如果wait
为0
并且leading
为false
,func
调用将被推迟到下一个点,类似setTimeout
为0
的超时。
trailing
leading
参数
func
(Function): 要防抖动的函数。
[wait=0]
(number): 需要延迟的毫秒数。
[options=]
(Object): 选项对象。
[options.leading=false]
(boolean): 指定在延迟开始前调用。
[options.maxWait]
(number): 设置 func 允许被延迟的最大值。
[options.trailing=true]
(boolean): 指定在延迟结束后调用。
返回
(Function): 返回新的debounced
(防抖动)函数。
示例// 避免窗口在变动时出现昂贵的计算开销。 jQuery(window).on('resize', _.debounce(calculateLayout, 150)); // 当点击时 `sendMail` 随后就被调用。 jQuery(element).on('click', _.debounce(sendMail, 300, { 'leading': true, 'trailing': false })); // 确保 `batchLog` 调用 1 次之后,1 秒内会被触发。 var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); var source = new EventSource('/stream'); jQuery(source).on('message', debounced); // 取消一个 trailing 的防抖动调用 jQuery(window).on('popstate', debounced.cancel);
-
_.throttle(func, [wait=0], [options=])
//节流 一般在点击按钮多次,但只希望生效 1(或尽可能少)次的时候使用。
创建一个节流函数,在wait
秒内最多执行func
一次的函数。 该函数提供一个cancel
方法取消延迟的函数调用以及flush
方法立即调用。 可以提供一个options
对象决定如何调用func
方法,options.leading
与|或options.trailing
决定wait
前后如何触发。func
会传入最后一次传入的参数给这个函数。 随后调用的函数返回是最后一次func
调用的结果。
注意: 如果leading
和trailing
都设定为true
则func
允许trailing
方式调用的条件为: 在wait
期间多次调用。
如果wait
为0
并且leading
为false
,func
调用将被推迟到下一个点,类似setTimeout
为0
的超时。
参数
func
(Function): 要节流的函数。
[wait=0]
(number): 需要节流的毫秒。
[options=]
(Object): 选项对象。
[options.leading=true]
(boolean): 指定调用在节流开始前。
[options.trailing=true]
(boolean): 指定调用在节流结束后。
返回
(Function): 返回节流的函数。
示例// 避免在滚动时过分的更新定位 jQuery(window).on('scroll', _.throttle(updatePosition, 100)); // 点击后就调用 `renewToken`,但 5 分钟内超过 1 次。 var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); jQuery(element).on('click', throttled); // 取消一个 trailing 的节流调用。 jQuery(window).on('popstate', throttled.cancel);
语言
- _.cloneDeep(value)
这个方法类似_.clone
,除了它会递归拷贝value
。(注:也叫深拷贝)。
参数
value
(): 要深拷贝的值。
返回
(): 返回拷贝后的值。
示例var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false
- _.isArray(value)
检查value
是否是Array
类对象。
返回
(boolean): 如果value
是一个数组返回true
,否则返回false
。
示例_.isArray([1, 2, 3]); // => true _.isArray(document.body.children); // => false _.isArray('abc'); // => false _.isArray(_.noop); // => false
字符串
-
_.startsWith([string=‘’], [target], [position=0])
检查字符串string
是否以target
开头。 -
_.endsWith([string=‘’], [target], [position=string.length])
检查字符串string
是否以给定的target
字符串结尾。 -
_.padEnd([string=‘’], [length=0], [chars=’ '])
如果string
字符串长度小于length
则在右侧填充字符。 如果超出length
长度则截断超出的部分。
参数
[string='']
(string): 要填充的字符串。
[length=0]
(number): 填充的长度。
[chars=' ']
(string): 填充字符。
返回
(string): 返回填充后的字符串。
示例_.padEnd('abc', 6); // => 'abc ' _.padEnd('abc', 6, '_-'); // => 'abc_-_' _.padEnd('abc', 3); // => 'abc'
-
_.padStart([string=‘’], [length=0], [chars=’ '])
如果string
字符串长度小于length
则在左侧填充字符。 如果超出length
长度则截断超出的部分。
示例_.padStart('abc', 6); // => ' abc' _.padStart('abc', 6, '_-'); // => '_-_abc' _.padStart('abc', 3); // => 'abc'
-
_.repeat([string=‘’], [n=1])
重复N
次给定字符串。
示例_.repeat('*', 3); // => '***' _.repeat('abc', 2); // => 'abcabc' _.repeat('abc', 0); // => ''
-
_.trim([string=‘’], [chars=whitespace])
从string
字符串中移除前面和后面的 空格 或 指定的字符。
示例_.trim(' abc '); // => 'abc' _.trim('-_-abc-_-', '_-'); // => 'abc' _.map([' foo ', ' bar '], _.trim); // => ['foo', 'bar']
-
_.trimEnd([string=‘’], [chars=whitespace])
从string
字符串中移除后面的 空格 或 指定的字符。 -
_.trimStart([string=‘’], [chars=whitespace])
从string
字符串中移除前面的 空格 或 指定的字符。 -
_.truncate([string=‘’], [options={}])
截断string
字符串,如果字符串超出了限定的最大值。 被截断的字符串后面会以 omission 代替,omission 默认是 “…”。
参数
[string='']
(string): 要截断的字符串。
[options=]
(Object): 选项对象。
[options.length=30]
(number): 允许的最大长度。
[options.omission='...']
(string): 超出后的代替字符。
[options.separator]
(RegExp|string): 截断点。
示例_.truncate('hi-diddly-ho there, neighborino'); // => 'hi-diddly-ho there, neighbo...' _.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 [...]'
实用函数
-
_ .times(n, [iteratee=_.identity])
调用 iterateen
次,每次调用返回的结果存入到数组中。 iteratee 调用入1个参数: (index)。
参数
n
(number): 调用iteratee
的次数。
[iteratee=_.identity]
(Function): 每次迭代调用的函数。
返回
(Array): 返回调用结果的数组。
示例_.times(3, String); // => ['0', '1', '2'] _.times(4, _.constant(0)); // => [0, 0, 0, 0]
-
_.constant(value)
创建一个返回value
的函数。
示例var objects = _.times(2, _.constant({ 'a': 1 })); console.log(objects); // => [{ 'a': 1 }, { 'a': 1 }] console.log(objects[0] === objects[1]); // => true
-
_.noop()
这个方法返回undefined
。
示例_.times(2, _.noop); // => [undefined, undefined]
-
_.range([start=0], end, [step=1])(可创建有规律的数组,如生成 1 到 100 的数组 [1,2,3,4,5…100])
创建一个包含从start
到end
,但不包含end
本身范围数字的数组。 如果start
是负数,而end
或step
没有指定,那么step
从-1
为开始。 如果end
没有指定,start
设置为0
。 如果end
小于start
,会创建一个空数组,除非指定了step
。
注意:: JavaScript 遵循 IEEE-754 标准处理无法预料的浮点数结果。
参数
[start=0]
(number): 开始的范围。
end
(number): 结束的范围。
[step=1]
(number): 范围的增量 或者 减量。
返回
(Array): 返回范围内数字组成的新数组。
示例_.range(4); // => [0, 1, 2, 3] _.range(-4); // => [0, -1, -2, -3] _.range(1, 5); // => [1, 2, 3, 4] _.range(0, 20, 5); // => [0, 5, 10, 15] _.range(0, -4, -1); // => [0, -1, -2, -3] _.range(1, 4, 0); // => [1, 1, 1] _.range(0); // => []
补充
SameValueZero
- 这个是 eq 遵循的规范,如下:
- 如果
x
和y
的类型不同,返回false
- 如果
x
的类型为Number
:
a. 如果x
为NaN
并且y
为NaN
,返回true
b. 如果x
为+0
并且 y 为-0
,返回true
c. 如果x
为-0
并且 y 为+0
, 返回true
d. 如果x
和y
的数值一致,返回true
e. 返回false
- 按照
SameValueNonNumber
的结果返回
- 如果
- 这个是 eq 遵循的规范,如下:
SameValueNonNumber
这个规范规定比较的值x
和y
都不为Number
类型,规范如下:x
的类型不为Number
类型y
的类型与x
的类型一致- 如果
x
的类型为Undefined
,返回true
- 如果
x
的类型为Null
,返回true
- 如果
x
的类型为String
,并且x
和y
的长度及编码相同,返回true
,否则返回false
- 如果
x
的类型为Boolean
,并且x
和y
同为true
或同为false
,返回true
,否则返回false
- 如果
x
的类型为Symbol
,并且x
和y
具有相同的Symbol
值,返回true
,否则返回false
- 如果
x
和y
指向同一个对象,返回true
, 否则返回false
_.debounce
和_.throttle
的区别_.debounce
: 允许我们将多个连续调用“组合”在一个中。
场景应用:
浏览器的resize
事件,借助防抖我们只需要关注用户拖动窗口的最后一次的值。
用户输入内容时,使用防抖只在用户停止输入时触发事件。比如等到用户停止输入之后再验证其输入值。 提示“您的密码太短”之类的消息。_.throttle
:不允许我们的函数每X
毫秒执行一次以上。
这与_.debounce
的主要区别在于,_.throttle
保证函数定期执行,至少每X
毫秒执行一次。
场景应用:
例如每200
毫秒检查一次你的滚动位置来触发一个 CSS 动画。
例如上滑加载,我们需要检测用户距离底部多远,当用户接近底部时,我们需要发送 ajax 请求数据回来。在这里,_.debounce
没用,因为它只在用户停止滚动时触发,而我们需要在用户到达底部之前获取数据。而_.throttle
可以让我们不停检测距离底部多远。- 更多详细信息可访问 David Corbacho’s article 了解两者间的区别。