实现常规的数组API:Array.prototype.map/filter/reduce
不会的,多练习几次,理解
Array.protptype.mockMap = function (fn, context) {
let arr = this || []
let res = []
for(let i=0;i<arr.length;i++) {
res.push(fn.apply(context, [arr[i],i,arr]))
}
return res
}
Array.prototype.mockFilter = function (fn, context) {
var arr = Array.prototype.slice.call(this);
var res = [];
for (let i = 0; i < arr.length; i++) {
var isSatisfy = fn.call(null, arr[i], i, this);
if (isSatisfy) {
res.push(arr[i]);
}
}
return res;
};
Array.prototype.mockReduce = function (fn, init) {
let arr = [];
let res = init ? init : arr[0];
let startIndex = init ? 0 : 1;
for (let i = startIndex; i < arr.length; i++) {
res = fn.call(this, res, arr[i], i, arr);
}
return res;
};
稍微进阶,改造 forEach,使其可终止遍历?
Array.prototype.mockForEach = function (fn, context) {
let arr = this || [];
let flag = false;
for (let i = 0; i < arr.length; i++) {
flag = fn.call(context, arr[i], i, arr);
if (flag) {
break;
}
}
};
let arr = [1, 2, 3, 4, 5];
arr.mockForEach((item, i, arr) => {
console.log(item, i, arr);
if (item == 3) {
return true;
}
});
// 后面 45 不会继续打印
1 0 (5) [1, 2, 3, 4, 5]
2 1 (5) [1, 2, 3, 4, 5]
3 2 (5) [1, 2, 3, 4, 5]
再次进阶,实现Array.prototype.group
小红书面试貌似很喜欢考
var array = [1, 2, 3, 4, 5]; // sorted
// expected
var result = {
bigger: [4, 5],
smaller: [1, 2, 3],
};
Array.prototype.group = function (fn) {
let arr = this || [];
let res = {};
for (let i = 0; i < arr.length; i++) {
let val = fn.apply(this, [arr[i], i, this]);
res[val] = res[val] ? [...res[val], arr[i]] : [arr[i]];
}
return res;
};
var res = array.group((num, index, array) => {
return num > 3 ? 'bigger' : 'smaller';
});
console.log(res);
进阶,实现数组新版API:Array.prototype.flatMap
flatMap() 方法对数组中的每个元素应用给定的回调函数,然后将结果展开一级,返回一个新数组。它等价于在调用 map() 方法后再调用深度为 1 的 flat() 方法(arr.map(...args).flat()),但比分别调用这两个方法稍微更高效一些。
示例
const arr1 = [1, 2, 1];
const result = arr1.flatMap((num) => (num === 2 ? [2, 2] : 1));
console.log(result);
// Expected output: Array [1, 2, 2, 1]
思考下,如何实现这个api
Array.prototype.mockFlatMap = function (fn, context) {
let arr = this || [];
let res = [];
for (let i = 0; i < arr.length; i++) {
let remain = fn.call(this, arr[i], i, arr);
if (Array.isArray(remain)) {
// 递归
res.push(...remain.mockFlatMap((x) => x));
} else {
res.push(remain);
}
}
return res;
};
// test
var array1 = [1, 4, 9, 16];
var map2 = array1.mockFlatMap((x) => (x === 1 ? [] : [x * 2]));
console.log(map2); // [8,18,32]
var test2 = [1, 2, 1];
var result = test2.flatMap((num) => (num === 2 ? [2, 2] : 1));
// Expected output: Array [1, 2, 2, 1]
console.log(result);
var res2 = test2.mockFlatMap((num) => (num === 3 ? [2, 2] : 1));
console.log(res2); // [1,1,1]