underscore.js 源码分析(四)
_.min
_.sortBy
_.groupBy
_.indexBy
_.countBy
_.min
_.min(list, [iteratee], [context])
类似于使用 _.max
这个函数用于获取到 list
中的最小值, 其中 iteratee
是作为的筛选的依据。源码如下:1 | _.min = function(obj, iteratee, context) { |
_.sortBy
_.sortBy(list, iteratee, [context])
使用 _.sortBy
返回的是一个经过排序之后的数组。排序的依据是根据 iteratee
函数进行判断的。返回的是进行排序之后的数组的副本,原来的数组并没有进行了改变。实例
源码分析
1 | _.sortBy = function(obj, iteratee, context) { |
_.sortBy
函数中存在着多个的函数,下面一一进行分析。_.pluck
函数,这个函数用于获取到对象数组中包含有过相关属性的所有的对象。看来是用 _.map...
这个方法返回的是一个对象数组。1 | // _.pluck 函数用于 |
_.map...
中执行了两步操作: 调用了使用的 _.map
方法以及接下来调用 sort
方法。1 | // _.map 方法 obj 是一个对象数组 |
_.map
方法返回的一个新的数组对象之后, 对于这个新的对象数组执行 sort
方法。关于数组的 sort
方法:关于使用数组的
sort
方法1 | Array.sort(sortBy); |
使用 sort() 方法的时候,如果不传递例如:sortBy
的时候,使用数组的sort
方法默认的是按照字符编码的顺序进行排序
1 | let a = [1, 2, 4, 23]; |
sortBy
是用来进行排序的函数:sortBy
接收两个参数,用来对于这两个参数进行比较。接下来执行的是
sort
函数1 | .sort(function(left, right) { |
sort
排序。 返回的是 _.comparator(left.criteria, right.criteria)
或者 left.index - right.index
。看来是用进行比较。其中 _.comparator
的方法。1 | // 传入要进行比较的函数参数 a, b |
_.groupBy
实例
_.groupBy(list, iteratee, [context])
将一个集合分为多个的集合,通过使用 iteratee
函数进行分组,如果 iteratee
是一个字符串而不是一个函数的时候,将这个 iteratee
作为元素的属性名来进行分组。如下:1 | _.groupBy([1, 2, 4], function(num) {return num % 2;}) // { 0: [2, 4], 1: [1] } |
源码解析
1 | _.groupBy = group(function(result, value, key) { |
group
以及 _.has
关于使用 group
函数:1 | // 接收一个 behavior 作为参数 |
behavior
函数是在 _.groupBy
中的函数是下面的这个:1 | if (_.has(result, key)) result[key].push(value); else result[key] = [value]; |
_.has
方法用来判断对象 result
中是否含有属性 key
:_.has
方法如下:1 | let _.has = function (obj, key) { |
_.indexBy
_.indexBy(list, iteratee, [context])
使用 _.indexBy
用来返回在列表中每一个元素键的 iteratee
函数。 返回一个每一项索引的对象。使用_.indexBy
和使用_.groupBy
的区别在于:使用_.indexBy
你需要知道键值对是唯一的,比如:
1
2
3
4
5
6
7
8 >let list = [{name: '张宁宁', age: 20}, {name: '张宁宁', age: 50}];
>_.indexBy(list, function(value) { return value.name });
>=>
>{张宁宁:{name: "张宁宁", age: 50}}
>_.groupBy(list, function(value) { return value.name });
>=>
>{张宁宁:[{name: '张宁宁', age: 20}, {name: '张宁宁', age: 50}]};
>
实例
1 | let list = [{name: '张三', age: 12}, {name: '李四', age: 13}]; |
源码解析
类似于使用_.groupBy
的源码, 使用 _.indexBy
的源码如下:1 | _.indexBy = group(function(result, value, key) { |
_.countBy
_.countBy(list, iteratee, [context])
返回各组中对象的数量的计数。返回在该组中值的数目。实例
1 | let list = [{name: '张宁宁', age: 20}, {name: '张宁宁', age: 50}]; |
源码如下
1 | let _.countBy = group(function(result, value, key) { |
group
](# group) 函数;shuffle
实例
用来返回一个随机乱序的副本。并没有改变list
的值。1 | let list = [1, 2, 3, 4, 5, 6]; |
源码分析
使用_.shuffle
的源码如下:1 | _.shuffle = function(obj) { |
_.random
的函数如下:1 | // 这个函数的目的是用来生成 |
Math.floor
: 向下取整Math.random
用于生成 0 - 1
之间的随机数;注意: 使用的是生成min
和max
之间的值得时候:min
: inclusive 包括max
: exclusive 不包括
1 | Math.random() * (max - min) + min |
shuffle
函数中,使用了一个分牌算法:1 | for (var index = 0, rand; index < length; index++) { |
使用 分牌算法的原理如下:存在两个数组 a 和 b现在想要将 a 中的元素随机生成到 b 中
1 | a-->b: index |
如上图所示的算法:
1 | Alice->Bob: Hello Bob, how are you? |