普通地實現 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