js手写题:数组类的应用场景

85 阅读2分钟

实现常规的数组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]