lodash-5 findIndex,findLastIndex

225 阅读2分钟

前言

今天是 lodash 的第5篇,感觉还可以,继续努力!

今天是 findIndexfindLastIndex 这两个 api

Api

_.findIndex(array, [predicate=_.identity], [fromIndex=0])

Arguments

  1. array  (Array) : The array to inspect(检查).
  2. [predicate=_.identity]  (Function) : The function invoked per iteration(迭代).
  3. [fromIndex=0]  (number) : The index to search from.

Returns

(number) : Returns the index of the found element, else -1.

Example

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

虽然 官方例子中写的很全,但是看过源码之后,发现 example 缺少一种情况,就是可以传入初始搜索的开始 index 下标

// 添加初始查找下标 1
_.findIndex(users, function(o) { return o.user == 'barney'; }, 1);
// => -1

可以看出,findIndex 可以接受 函数/ 对象 / 数组 / 字符串 作为查找条件

source

function findIndex(array, predicate, fromIndex) {
  var length = array == null ? 0 : array.length;
  if (!length) {
    return -1;
  }
  var index = fromIndex == null ? 0 : toInteger(fromIndex);
  if (index < 0) {
    index = nativeMax(length + index, 0);
  }
  return baseFindIndex(array, baseIteratee(predicate, 3), index);
}

简化版

function findIndex(array, predicate, fromIndex) {
  var length =  array.length;
  var index = fromIndex == null ? 0 : fromIndex;
 
  return baseFindIndex(array, baseIteratee(predicate), index);
}

baseIteratee

这个 baseIteratee 在经常遇到,今天不再赘述,简单写一下

baseIteratee 根据各种情况生成一个调用函数,函数的返回值是 boolean 类型

function baseIteratee(value) {
 //value 类型 函数类型
  if (typeof value == 'function') {
    return value;
  }
  
  if (typeof value == 'object') {
   //  ['active', false]
    return Array.isArray(value)
      ? (object)=>{
          return object[value[0]] == value[1]
      }
      //  { 'user': 'fred', 'active': false }
      : baseMatches(value);
  }
  // value 类型 为 字符串
  return (object)=>object[value]
}
baseMatches

使用 闭包matchDatasource 进行了缓存, 不用每次执行函数都重新生成 matchData

// { 'user': 'fred', 'active': false }
function baseMatches(source) {
   // [['user','fred'],['active','false']]
    var matchData = Object.entries(source);
    
    // 每次遍历 => object 的值
    // { 'user': 'barney',  'active': false },
    // { 'user': 'fred',    'active': false },
    // { 'user': 'pebbles', 'active': true }
    return function (object) {
        var index = matchData.length
        while (index--){
            var data = matchData[index];
            // 判断是否存在,如果存在判断 value 是否正确
            if (
              !(data[0] in object) ||
                 object[data[0]] !== data[1]
               ) {
                  return false;
              }
        }
    }
}

baseFindIndex

通过迭代函数 predicate 的返回值来寻找 index

function baseFindIndex(array, predicate, fromIndex, fromRight) {
// fromIndex 默认是 0,fromRight 默认时 undefined
// 没有是 fromRight ,index 默认为 fromIndex-1,说明是从左到右
// 如果有 fromRight,index 为 fromIndex + 1, // 从右到左
  var length = array.length,
      index = fromIndex + (fromRight ? 1 : -1);
 
 // 由于此时index 不参与 运算, --index 与 index-- 是一样的
  while ((fromRight ? index-- : ++index < length)) {
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  
  return -1;
}

如果 predicate 返回了 true,则说明找到了,返回index

_.findLastIndex(array, [predicate=_.identity], [fromIndex=array.length-1])

这个和上文的 findIndex 的使用是一样的,只不过这个是 从右往左 查找,也就是 baseFindIndex 的最后一个参数 fromRight 是 true

结尾

通过今天这两个 api的学习,了解到 函数式编程 的优势,也对 闭包 有更深刻的理解