手写实现Array.prototype.filter方法
理解并手动实现JavaScript数组的filter方法,掌握数组遍历和函数式编程的思想
问题
filter 是 JavaScript 数组的一个重要方法,用于筛选出满足条件的元素并返回一个新数组。我们需要手动实现一个功能完全相同的 myFilter 方法,理解其内部工作原理。
filter 方法接收一个回调函数作为参数,该回调函数会对数组中的每个元素进行测试,返回 true 的元素会被保留在新数组中。
解答
/**
* 手写实现 Array.prototype.filter 方法
* @param {Function} callback - 回调函数,接收三个参数:当前元素、索引、原数组
* @param {*} thisArg - 可选参数,执行回调函数时的 this 值
* @returns {Array} 返回一个新数组,包含所有通过测试的元素
*/
Array.prototype.myFilter = function(callback, thisArg) {
// 1. 检查调用对象是否为 null 或 undefined
if (this == null) {
throw new TypeError('Array.prototype.myFilter 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. 创建结果数组
const result = [];
// 6. 遍历数组
for (let i = 0; i < len; i++) {
// 检查索引是否存在(处理稀疏数组)
if (i in O) {
const element = O[i];
// 调用回调函数,传入当前元素、索引和原数组
// 使用 call 绑定 thisArg
if (callback.call(thisArg, element, i, O)) {
result.push(element);
}
}
}
// 7. 返回新数组
return result;
};
使用示例
// 示例1:筛选偶数
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.myFilter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6]
// 示例2:筛选对象数组
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 30 }
];
const adults = users.myFilter(user => user.age >= 18);
console.log(adults);
// [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 30 }]
// 示例3:使用 thisArg 参数
const filterConfig = {
minValue: 10
};
const values = [5, 15, 8, 20, 12];
const filtered = values.myFilter(function(num) {
return num >= this.minValue;
}, filterConfig);
console.log(filtered); // [15, 20, 12]
// 示例4:处理稀疏数组
const sparseArray = [1, , 3, , 5];
const result = sparseArray.myFilter(num => num > 2);
console.log(result); // [3, 5]
// 示例5:获取索引信息
const arr = ['a', 'b', 'c', 'd'];
const withIndex = arr.myFilter((item, index) => index % 2 === 0);
console.log(withIndex); // ['a', 'c']
关键点
- 参数校验:需要检查
this是否为null/undefined,以及callback是否为函数类型 - thisArg 绑定:使用
call方法将thisArg绑定到回调函数的执行上下文 - 稀疏数组处理:使用
in操作符检查索引是否存在,跳过空位元素 - 不修改原数组:创建新数组存储结果,保持原数组不变
- 回调函数参数:正确传递三个参数:当前元素值、当前索引、原数组对象
- 长度处理:使用
>>> 0无符号右移运算确保长度为非负整数 - 返回新数组:filter 方法总是返回一个新数组,即使没有元素通过测试也返回空数组
目录