# compareMultiple
# Description
由orderBy用来将一个值的多个属性与另一个进行比较,并对其进行稳定排序。
如果未指定orders,则所有值均按升序排序。否则,请为相应值的降序指定 desc
的顺序,或为升序指定 asc
的顺序。
# Params
(object, other, orders)
{(string|function)[]} orders - 可以指定多个维度的对比,为数组
const a = [
{type: 10, name: 'Java'},
{type: 20, name: 'JavaScript'},
{type: 5, name: 'python'},
]
这个时候就可以根据 type 和 name 进行排序,多个维度
# Return
number
# Depend
import compareAscending from './compareAscending.js'
# Code
function compareMultiple(object, other, orders) {
let index = -1
const objCriteria = object.criteria
const othCriteria = other.criteria
const length = objCriteria.length
const ordersLength = orders.length
while (++index < length) {
const order = index < ordersLength ? orders[index] : null
const cmpFn = (order && typeof order === 'function') ? order: compareAscending
const result = cmpFn(objCriteria[index], othCriteria[index])
if (result) {
if (order && typeof order !== 'function') {
return result * (order == 'desc' ? -1 : 1)
}
return result
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to provide the same value for
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
// for more details.
//
// This also ensures a stable sort in V8 and other engines.
// See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
return object.index - other.index
}
# Analyze
- 首先获取到
object
和other
的criteria
的值,拿到objCriteria
和orders
的length
while
循环进行排序,条件是objCriteria
的length > index
- 首先拿到每一个
order
,根据orders
length
是否大于 当前迭代的下标,满足条件取对应的order
, 否则为null
- 每个维度都有自己的
cmpFn
函数,用来比较排序,如果order
不存在,或者order
不是function
,则使用默认的compareAscending
来进行比较 - 调用
cmpFn
拿到比较的结果 - 如果
result
不为 0,判断order
如果不是function
,则判断升序或降序,如果order
为desc
,则降序排列,乘以-1 取反
- 如果
while
循环完成后,都没有得到结果,或者结果为0,则使用object.index - other.index
,如果直接返回undefined
,在 V8 中不能确保稳定排序,则使用object.index - other.index
,这个index
属性,是baseOrderBy
在调用时,会生成的,这里会返回0
# Remark
- compareMultiple 为lodash 内部使用的方法,所以对于 criteria 和 index 属性是会从调用的地方传入的, compareMultiple 函数 如果不传入这些,结果和预期就会有差,甚至有可能会报错
- 整个 orderBy 排序,最终会使用到 Array.prototype.sort() (opens new window) 来进行排序修改
# Example
console.log(compareMultiple({a:1, criteria: ['a'], index: 0}, {a:1, criteria: ['a'],index: 0}, ['desc'])) // 0