find

_.find(list, predicate, [context])Alias: detect
list 中逐项查找,返回第一个通过 predicate 迭代函数真值检测的元素值,如果没有元素通过检测则返回 undefined。 如果找到匹配的元素,函数将立即返回,不会遍历整个 list。predicate 通过 iteratee 进行转换,以简化速记语法。

1
2
var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> 2

find.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import isArrayLike from './_isArrayLike.js';
// 是否类数组,在01 each 中有展示
import findIndex from './findIndex.js';
import findKey from './findKey.js';

// 返回第一个匹配的结果
export default function find(obj, predicate, context) {
// 是否是类数组,是数组查索引(下标),不是查键名
var keyFinder = isArrayLike(obj) ? findIndex : findKey;
// 查询的结果
var key = keyFinder(obj, predicate, context);
if (key !== void 0 && key !== -1) return obj[key];
}

findIndex.js

1
2
3
4
import createPredicateIndexFinder from './_createPredicateIndexFinder.js';

// 返回判断结果为真的第一个索引
export default createPredicateIndexFinder(1);

_createPredicateIndexFinder.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import cb from './_cb.js';
import getLength from './_getLength.js';

// 根据传入的方向,生成 findIndex 和 findLastIndex(从前面开始查,还是后面开始查)
export default function createPredicateIndexFinder(dir) {
// 传入数组,条件函数,上下文
return function(array, predicate, context) {
// 把条件函数的 this 指向当前上下文
predicate = cb(predicate, context);
var length = getLength(array);
// 起始索引
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
// 执行条件函数,传入数组的当前项,索引,以及数组本身
// 如果结果为真,返回当前索引
if (predicate(array[index], index, array)) return index;
}
// 没有符合条件的返回 -1
return -1;
};
}

findKey.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cb from './_cb.js';
import keys from './keys.js';

// 返回通过真值测试的第一个键名
export default function findKey(obj, predicate, context) {
// 把条件函数的 this 指向当前上下文
predicate = cb(predicate, context);
// Object.keys() 的向下兼容版本
var _keys = keys(obj), key;
for (var i = 0, length = _keys.length; i < length; i++) {
key = _keys[i];
// 返回符合条件的索引
if (predicate(obj[key], key, obj)) return key;
}
}