实现findIndex方法

手写实现数组的findIndex方法,返回第一个满足条件的元素索引

问题

findIndex 是 ES6 中数组的一个方法,用于查找数组中第一个满足测试函数条件的元素,并返回该元素的索引。如果没有找到满足条件的元素,则返回 -1。

我们需要手动实现这个方法,支持:

  • 接收一个回调函数作为参数
  • 回调函数接收三个参数:当前元素、当前索引、原数组
  • 支持传入 thisArg 改变回调函数的 this 指向
  • 返回第一个满足条件的元素索引,否则返回 -1

解答

/**
 * 实现 Array.prototype.findIndex 方法
 * @param {Function} callback - 测试函数
 * @param {*} thisArg - 可选,执行 callback 时的 this 值
 * @returns {number} 返回第一个满足条件的元素索引,否则返回 -1
 */
Array.prototype.myFindIndex = function(callback, thisArg) {
  // 检查调用对象是否为 null 或 undefined
  if (this == null) {
    throw new TypeError('Array.prototype.myFindIndex called on null or undefined');
  }
  
  // 检查 callback 是否为函数
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  
  // 将调用对象转换为对象
  const obj = Object(this);
  // 获取数组长度,使用无符号右移确保为非负整数
  const len = obj.length >>> 0;
  
  // 遍历数组
  for (let i = 0; i < len; i++) {
    // 检查索引是否存在(处理稀疏数组)
    if (i in obj) {
      // 调用回调函数,传入当前元素、索引和原数组
      // 使用 call 绑定 thisArg
      if (callback.call(thisArg, obj[i], i, obj)) {
        return i; // 找到满足条件的元素,返回索引
      }
    }
  }
  
  // 没有找到满足条件的元素,返回 -1
  return -1;
};

使用示例

// 示例1:查找第一个大于 10 的数字的索引
const numbers = [5, 8, 12, 15, 20];
const index1 = numbers.myFindIndex(num => num > 10);
console.log(index1); // 输出: 2

// 示例2:查找第一个偶数的索引
const numbers2 = [1, 3, 5, 8, 9];
const index2 = numbers2.myFindIndex(num => num % 2 === 0);
console.log(index2); // 输出: 3

// 示例3:未找到满足条件的元素
const numbers3 = [1, 3, 5, 7];
const index3 = numbers3.myFindIndex(num => num > 10);
console.log(index3); // 输出: -1

// 示例4:使用索引参数
const arr = ['a', 'b', 'c', 'd'];
const index4 = arr.myFindIndex((item, index) => index === 2);
console.log(index4); // 输出: 2

// 示例5:使用 thisArg 参数
const threshold = {
  min: 10,
  max: 20
};
const numbers4 = [5, 15, 25, 30];
const index5 = numbers4.myFindIndex(function(num) {
  return num >= this.min && num <= this.max;
}, threshold);
console.log(index5); // 输出: 1

// 示例6:查找对象数组
const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 35 }
];
const index6 = users.myFindIndex(user => user.name === 'Bob');
console.log(index6); // 输出: 1

关键点

  • 参数校验:需要检查 this 是否为 null/undefined,以及 callback 是否为函数类型
  • 类型转换:使用 Object(this) 将调用对象转换为对象,使用 >>> 0 确保长度为非负整数
  • 遍历逻辑:使用 for 循环遍历数组,找到第一个满足条件的元素立即返回索引
  • 稀疏数组处理:使用 in 操作符检查索引是否存在,跳过空位
  • this 绑定:使用 call 方法将 thisArg 绑定到回调函数的 this 上
  • 返回值:找到满足条件的元素返回索引,否则返回 -1
  • 回调函数参数:回调函数接收三个参数:当前元素值、当前索引、原数组对象