Skip to main content

手写数组方法

手写 reduce/map/filter/forEach/flat 等是高频题,重点在 回调参数 (item, index, array)this 指向、空数组/无初始值等边界

map 的实现见 数组相关

reduce

最容易踩坑的是不传初始值的情况:用第一个元素作为初始值,并从下标 1 开始;空数组无初始值要抛错。

Array.prototype.myReduce = function (fn, initialValue) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
const arr = this;
let acc;
let startIndex = 0;

if (arguments.length >= 2) {
acc = initialValue;
} else {
if (arr.length === 0) {
throw new TypeError("Reduce of empty array with no initial value");
}
acc = arr[0];
startIndex = 1;
}

for (let i = startIndex; i < arr.length; i++) {
acc = fn(acc, arr[i], i, arr);
}
return acc;
};

filter

Array.prototype.myFilter = function (fn, thisArg) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
const res = [];
for (let i = 0; i < this.length; i++) {
if (fn.call(thisArg, this[i], i, this)) {
res.push(this[i]);
}
}
return res;
};

forEach

Array.prototype.myForEach = function (fn, thisArg) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
for (let i = 0; i < this.length; i++) {
fn.call(thisArg, this[i], i, this);
}
};

flat(支持深度)

function flat(arr, depth = 1) {
if (depth <= 0) return arr.slice();
return arr.reduce(
(acc, cur) =>
acc.concat(Array.isArray(cur) ? flat(cur, depth - 1) : cur),
[]
);
}

// 完全拉平:depth 传 Infinity
flat([1, [2, [3, [4]]]], Infinity); // [1, 2, 3, 4]

数组扁平化的更多写法见 数组扁平化