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? |