# 数组方法

# 1. 概述

JavaScript 数组提供了许多实用的方法,本文实现了以下常用方法的自定义版本:

  • 遍历方法: forEach, map, filter
  • 查找方法: find, findIndex, includes
  • 归并方法: reduce
  • 判断方法: some, every
  • 排序方法: sort

# 2. 方法实现

# 2.1. forEach - 遍历数组

// 自定义 forEach 方法
Array.prototype.myForEach = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myForEach called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    for (let i = 0; i < len; i++) {
        if (i in arr) {
            fn.call(undefined, arr[i], i, arr);
        }
    }
}

# 2.2. map - 映射数组

// 自定义 map 方法
Array.prototype.myMap = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myMap called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    const result = new Array(len);
    
    for (let i = 0; i < len; i++) {
        if (i in arr) {
            result[i] = fn.call(undefined, arr[i], i, arr);
        }
    }
    
    return result;
}

# 2.3. filter - 过滤数组

// 自定义 filter 方法
Array.prototype.myFilter = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myFilter called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    const result = [];
    
    for (let i = 0; i < len; i++) {
        if (i in arr && fn.call(undefined, arr[i], i, arr)) {
            result.push(arr[i]);
        }
    }
    
    return result;
}

# 2.4. find - 查找元素

// 自定义 find 方法
Array.prototype.myFind = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myFind called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    for (let i = 0; i < len; i++) {
        if (i in arr && fn.call(undefined, arr[i], i, arr)) {
            return arr[i];
        }
    }
    
    return undefined;
}

# 2.5. findIndex - 查找索引

// 自定义 findIndex 方法
Array.prototype.myFindIndex = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myFindIndex called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    for (let i = 0; i < len; i++) {
        if (i in arr && fn.call(undefined, arr[i], i, arr)) {
            return i;
        }
    }
    
    return -1;
}

# 2.6. reduce - 归并数组

// 自定义 reduce 方法
Array.prototype.myReduce = function (fn, initialValue) {
    if (this == null) {
        throw new TypeError('Array.prototype.myReduce called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    let accumulator;
    let startIndex;
    
    if (arguments.length > 1) {
        accumulator = initialValue;
        startIndex = 0;
    } else {
        if (len === 0) {
            throw new TypeError('Reduce of empty array with no initial value');
        }
        accumulator = arr[0];
        startIndex = 1;
    }
    
    for (let i = startIndex; i < len; i++) {
        if (i in arr) {
            accumulator = fn.call(undefined, accumulator, arr[i], i, arr);
        }
    }
    
    return accumulator;
}

# 2.7. some - 至少一个匹配

// 自定义 some 方法
Array.prototype.mySome = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.mySome called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    for (let i = 0; i < len; i++) {
        if (i in arr && fn.call(undefined, arr[i], i, arr)) {
            return true;
        }
    }
    
    return false;
}

# 2.8. every - 全部匹配

// 自定义 every 方法
Array.prototype.myEvery = function (fn) {
    if (this == null) {
        throw new TypeError('Array.prototype.myEvery called on null or undefined');
    }
    if (typeof fn !== 'function') {
        throw new TypeError('fn must be a function');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    for (let i = 0; i < len; i++) {
        if (i in arr && !fn.call(undefined, arr[i], i, arr)) {
            return false;
        }
    }
    
    return true;
}

# 2.9. sort - 排序数组

// 自定义 sort 方法 (简单冒泡排序)
Array.prototype.mySort = function (compareFn) {
    if (this == null) {
        throw new TypeError('Array.prototype.mySort called on null or undefined');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    if (typeof compareFn !== 'function') {
        compareFn = (a, b) => String(a).localeCompare(String(b));
    }
    
    // 冒泡排序
    for (let i = 0; i < len - 1; i++) {
        for (let j = 0; j < len - 1 - i; j++) {
            if (compareFn(arr[j], arr[j + 1]) > 0) {
                const temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    
    return arr;
}

# 2.10. includes - 包含元素

// 自定义 includes 方法
Array.prototype.myIncludes = function (searchElement, fromIndex = 0) {
    if (this == null) {
        throw new TypeError('Array.prototype.myIncludes called on null or undefined');
    }
    
    const arr = Object(this);
    const len = arr.length >>> 0;
    
    if (len === 0) return false;
    
    let startIndex = fromIndex || 0;
    if (startIndex >= len) return false;
    
    if (startIndex < 0) {
        startIndex = len + startIndex;
        if (startIndex < 0) startIndex = 0;
    }
    
    for (let i = startIndex; i < len; i++) {
        if (i in arr) {
            if (Object.is(searchElement, arr[i]) || 
                (searchElement !== searchElement && arr[i] !== arr[i])) {
                return true;
            }
        }
    }
    
    return false;
}

# 4. 使用说明

# 4.1. 注意事项

  • 所有方法都对 nullundefined 进行类型检查
  • 回调函数参数必须为函数类型
  • 使用 >>> 0 确保长度为无符号整数
  • 正确处理稀疏数组 (跳过空索引)
  • includes 方法支持 NaN 的比较 (使用 Object.is)
本章目录