普通地实现 findIndex 与 findLastIndex
ES6 新增了 findIndex 与 findLastIndex 数组方法,可以正序、反序地查询,并返回数组中满足回调函数的第一个元素的索引,否则返回 -1。
// 用法
arrayObj.findIndex(callbackfn [, thisArg]);
// 回调函数用法
function callbackfn(value, index, arrayObj)
实现 findIndex():
只需要遍历元素,逐个判断即可。
思路明确,代码如下
代码:
Array.prototype.fakeFindIndex = function (cb, context) {
let array = this;
for (let i = 0; i < array.length; i++) {
const element = array[i];
if (cb.call(context, element, i, array)) {
return i
}
}
return -1
}
简单测试:
console.log([9, 9, 6].fakeFindIndex(item => (item === 6)))
// 输出:2
实现 findLastIndex():
findLastIndex 与 前者的区别就在于它是逆序遍历的。所以,只需要改变 for 循环遍历顺序就可以了。
代码:
Array.prototype.fakeFindLastIndex = function (cb, context) {
let array = this;
for (let i = array.length-1; i >=0; i--) {
const element = array[i];
if (cb.call(context, element, i, array)) {
return i
}
}
return -1
}
简单测试:
console.log([10, 10, 6].fakeFindLastIndex(item => (item === 6)))
// 输出:2
用一个函数精简地实现
上面两个函数的区别很小,重复代码很多。
underscore 用一个函数实现了它们,巧妙地用一个参数来控制遍历顺序:
当参数 dir:
- 为 1:得到正序遍历方法;
- 为 -1: 得到逆序遍历方法。
道理简单而巧妙,上代码:
代码
function createIndexFinder(dir) {
return function (array, cb, context) {
let length = array.length;
// 控制初始 index,0 或者 length-1
let index = dir >= 0 ? 0 : length - 1;
// 条件: 在数组范围内;
// 递增或递减:递加 1 或者 -1; 妙啊~
for( ; index >= 0 && index <= length - 1; index += dir ) {
if( cb.call(context, array[index], index) ) return index
}
return -1
}
}
用例:
const findIndex = createIndexFinder(1);
const findLastIndex = createIndexFinder(-1);
【空城下的司马懿脸:妙啊~】
参考:
https://github.com/mqyqingfeng/Blog/issues/37
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex