手写实现 Array.prototype.some 方法

从零实现 JavaScript 数组的 some 方法,理解其工作原理和实现细节

问题

Array.prototype.some() 是 JavaScript 数组的一个常用方法,用于测试数组中是否至少有一个元素通过了指定函数的测试。如果有任何一个元素满足条件,则返回 true,否则返回 false

本题要求手写实现一个功能完整的 some 方法,需要考虑:

  • 回调函数的参数传递(当前元素、索引、原数组)
  • this 绑定
  • 空数组的处理
  • 稀疏数组的处理

解答

/**
 * 手写实现 Array.prototype.some 方法
 * @param {Function} callback - 测试函数,接收三个参数:element, index, array
 * @param {*} thisArg - 执行 callback 时使用的 this 值
 * @returns {Boolean} - 如果至少有一个元素通过测试返回 true,否则返回 false
 */
Array.prototype.mySome = function(callback, thisArg) {
  // 1. 类型检查:确保调用对象可以转换为对象
  if (this == null) {
    throw new TypeError('Array.prototype.mySome called on null or undefined');
  }
  
  // 2. 检查 callback 是否为函数
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  
  // 3. 将调用对象转换为对象
  const O = Object(this);
  
  // 4. 获取数组长度,使用无符号右移确保为非负整数
  const len = O.length >>> 0;
  
  // 5. 遍历数组
  for (let i = 0; i < len; i++) {
    // 6. 只处理数组中实际存在的元素(处理稀疏数组)
    if (i in O) {
      // 7. 调用回调函数,传入当前元素、索引和原数组
      // 使用 call 绑定 thisArg
      if (callback.call(thisArg, O[i], i, O)) {
        // 8. 只要有一个元素满足条件,立即返回 true
        return true;
      }
    }
  }
  
  // 9. 所有元素都不满足条件,返回 false
  return false;
};

使用示例

// 示例1:基本使用
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.mySome(num => num % 2 === 0);
console.log(hasEven); // true

// 示例2:检查是否存在大于10的数
const hasGreaterThan10 = numbers.mySome(num => num > 10);
console.log(hasGreaterThan10); // false

// 示例3:使用 thisArg
const threshold = {
  min: 3
};
const hasGreaterThanMin = numbers.mySome(function(num) {
  return num > this.min;
}, threshold);
console.log(hasGreaterThanMin); // true

// 示例4:处理对象数组
const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 }
];
const hasAdult = users.mySome(user => user.age >= 18);
console.log(hasAdult); // true

// 示例5:空数组
const empty = [];
const result = empty.mySome(x => x > 0);
console.log(result); // false

// 示例6:稀疏数组
const sparse = [1, , 3, , 5];
const hasFour = sparse.mySome(num => num === 4);
console.log(hasFour); // false
console.log(sparse.mySome(num => num === 3)); // true

// 示例7:提前终止
const largeArray = Array.from({ length: 1000 }, (_, i) => i);
let count = 0;
largeArray.mySome(num => {
  count++;
  return num === 5; // 找到5就停止
});
console.log(count); // 6(只遍历了6次就找到了)

关键点

  • 类型检查:需要检查 this 是否为 nullundefined,以及 callback 是否为函数

  • 对象转换:使用 Object(this) 将调用对象转换为对象类型,确保兼容性

  • 长度处理:使用 >>> 0 无符号右移运算符确保长度为非负整数

  • 稀疏数组处理:使用 in 操作符检查索引是否存在,跳过数组中的空位

  • this 绑定:使用 callback.call(thisArg, ...) 正确绑定回调函数的 this 值

  • 短路特性:一旦找到满足条件的元素立即返回 true,不再继续遍历,提高性能

  • 空数组返回 false:对于空数组或所有元素都不满足条件的情况,返回 false

  • 不修改原数组some 方法不会修改原数组,只是进行测试判断