index里面有一个有趣的点:
查找值NaN的情形
//_.findIndex 特殊情况下的处理方案 NAN
//_.sortedIndex 针对排序的数组做二分查找 优化性能
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
function createIndexFinder(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {//console.log(_.indexOf([1,2,NaN, 4,5,6],NaN,true));
var i = 0,
length = array.length;
//先判断被查找的值是不是NaN,如果要查找的元素是 NaN 类型 NaN !== NaN
if (item !== item) {
console.log([].slice.call(array, i, length))
idx = predicateFind([].slice.call(array, i, length), _.isNaN);
//_.findIndex
return idx >= 0 ? idx + i : -1;
}
// 第三个参数true用二分查找优化 _.isBoolean(idx)为true代表idx是布尔值;idx为true代表排过序的; 否则 遍历查找
//如果先判断第三个参数true的话,被查找的是NaN的话,就会在下面这个if语句中输出-1;不会进入if (item !== item) {}里面;所以NaN值的判断应该放在前面;
if (sortedIndex && _.isBoolean(idx) && idx && length) {
// 能用二分查找加速的条件
// 用 _.sortedIndex 找到有序数组中 item
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
//有可能是idx,有可能是-1;
}
// 非上述情况正常遍历
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
}
二分法查找函数: sortedIndex
_.sortedIndex = function(array, obj, iteratee, context) {
// 重点:cb函数 if (iteratee == null) {return function(value){return value;}}这里很妙!
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0,
high = array.length;
// 二分查找
while (low < high) { //4 4
var mid = Math.floor((low + high) / 2); //4
if (iteratee(array[mid]) < value) // 5 < 5
low = mid + 1; //4 如果找不到就 low = mid + 1,
else
high = mid; //4 中间值赋值给high;
}
return low; //4 sortedIndex 一定会返回一个值;但是这个值不一定就是===value;
};