实现数组的 find 方法

手写实现 Array.prototype.find 方法,查找数组中第一个满足条件的元素

问题

Array.prototype.find() 方法用于查找数组中第一个满足测试函数条件的元素,并返回该元素的值。如果没有找到符合条件的元素,则返回 undefined。本题要求手动实现这个方法。

解答

/**
 * 实现数组的 find 方法
 * @param {Function} callback - 测试函数,接收三个参数:当前元素、索引、原数组
 * @param {*} thisArg - 执行 callback 时的 this 值
 * @returns {*} 返回第一个满足条件的元素,否则返回 undefined
 */
Array.prototype.myFind = function(callback, thisArg) {
  // 检查调用对象是否为 null 或 undefined
  if (this == null) {
    throw new TypeError('Array.prototype.myFind called on null or undefined');
  }
  
  // 检查 callback 是否为函数
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  
  // 将调用对象转换为对象
  const arr = Object(this);
  // 获取数组长度
  const len = arr.length >>> 0;
  
  // 遍历数组
  for (let i = 0; i < len; i++) {
    // 检查索引是否存在(处理稀疏数组)
    if (i in arr) {
      const element = arr[i];
      // 调用回调函数,如果返回 true,则返回当前元素
      if (callback.call(thisArg, element, i, arr)) {
        return element;
      }
    }
  }
  
  // 没有找到满足条件的元素,返回 undefined
  return undefined;
};

使用示例

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

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

// 示例 3:未找到元素
const result2 = numbers.myFind(num => num > 100);
console.log(result2); // 输出: undefined

// 示例 4:使用 thisArg 参数
const threshold = {
  min: 10,
  max: 20
};
const result3 = numbers.myFind(function(num) {
  return num >= this.min && num <= this.max;
}, threshold);
console.log(result3); // 输出: 12

// 示例 5:处理稀疏数组
const sparse = [1, , 3, , 5];
const result4 = sparse.myFind(num => num === undefined);
console.log(result4); // 输出: undefined(跳过空位)

关键点

  • 参数校验:需要检查 this 是否为 null/undefined,以及 callback 是否为函数
  • 类型转换:使用 Object(this) 将调用对象转换为对象,确保兼容性
  • 长度处理:使用 >>> 0 无符号右移运算符确保长度为非负整数
  • 稀疏数组处理:使用 in 操作符检查索引是否存在,跳过数组中的空位
  • thisArg 绑定:使用 call 方法绑定回调函数的 this
  • 提前返回:一旦找到满足条件的元素立即返回,不继续遍历
  • 默认返回值:如果遍历完整个数组都没有找到,返回 undefined
  • 回调函数参数:传递当前元素、索引和原数组三个参数给回调函数