数组实践与手写
如何给数组去重?
[...new Set(arr)]; // 利用 Set 唯一性
Array.from(new Set(arr));
for (const item of arr) {
if (!newArr.includes(item)) newArr.push(item);
}
arr.filter((item, index) => arr.indexOf(item, 0) === index); // 保留首次出现
常用数组方法如何手写实现?
Array.prototype.myMap = function (callback) {
const result = [];
for (let i = 0; i < this.length; i++) result.push(callback(this[i], i, this));
return result;
};
Array.prototype.myFilter = function (callback) {
const result = [];
for (let i = 0; i < this.length; i++) if (callback(this[i], i, this)) result.push(this[i]);
return result;
};
Array.prototype.myReduce = function (callback, initialValue) {
let accumulator = initialValue;
for (let i = 0; i < this.length; i++) {
accumulator = accumulator === undefined ? this[i] : callback(accumulator, this[i], i, this);
}
return accumulator;
};
Array.prototype.myFlat = function (depth = 1) {
const result = [];
const flatten = (arr, d) => {
arr.forEach((item) => {
if (Array.isArray(item) && d > 0) flatten(item, d - 1);
else result.push(item);
});
};
flatten(this, depth);
return result;
};
forEach、some、every、find的手写只需替换终止条件:some命中返回true,every失败返回false,find命中返回元素, 否则返回undefined;
forEach 为什么不能跳出循环?
- 原因:
forEach回调构成函数作用域, 回调内return只结束本次回调, 不会结束遍历; - 替代: 需要提前结束时用
some或every, 或改用for...of;
arr.forEach((item) => {
if (item > 2) return; // 只跳过本次, 循环继续
});
arr.some((item) => item > 2); // 遇到即返回 true 并停止
arr.every((item) => item <= 2); // 出现不满足即返回 false 并停止
如何把树与扁平数组互相转换?
// 树 → 扁平数组
const flattenTree = (tree) => {
if (!tree.children?.length) return [tree];
let res = [tree];
for (const child of tree.children) res = res.concat(flattenTree(child));
delete tree.children;
return res;
};
// 扁平数组 → 树
const buildTree = (array, parentId = null) =>
array.reduce((tree, cur) => {
if (cur.parentId === parentId) {
const children = buildTree(array, cur.id);
if (children.length > 0) cur.children = children;
tree.push(cur);
}
return tree;
}, []);