前言
今天是 lodash 的第5篇,感觉还可以,继续努力!
今天是 findIndex 和 findLastIndex 这两个 api
Api
_.findIndex(array, [predicate=_.identity], [fromIndex=0])
Arguments
array(Array) : The array to inspect(检查).[predicate=_.identity](Function) : The function invoked per iteration(迭代).[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
使用
闭包对matchData和source进行了缓存, 不用每次执行函数都重新生成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的学习,了解到 函数式编程 的优势,也对 闭包 有更深刻的理解