# 数组方法
# 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. 注意事项
- 所有方法都对
null和undefined进行类型检查 - 回调函数参数必须为函数类型
- 使用
>>> 0确保长度为无符号整数 - 正确处理稀疏数组 (跳过空索引)
includes方法支持NaN的比较 (使用Object.is)
上一篇: 下一篇:
本章目录