手写实现 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是否为null或undefined,以及callback是否为函数 -
对象转换:使用
Object(this)将调用对象转换为对象类型,确保兼容性 -
长度处理:使用
>>> 0无符号右移运算符确保长度为非负整数 -
稀疏数组处理:使用
in操作符检查索引是否存在,跳过数组中的空位 -
this 绑定:使用
callback.call(thisArg, ...)正确绑定回调函数的 this 值 -
短路特性:一旦找到满足条件的元素立即返回
true,不再继续遍历,提高性能 -
空数组返回 false:对于空数组或所有元素都不满足条件的情况,返回
false -
不修改原数组:
some方法不会修改原数组,只是进行测试判断
目录