如何在 JavaScript 中循环数组时递归调用自身内部的原型函数?

How do I recursively call a prototype function inside itself while looping an array in JavaScript?

我正在创建一个 Array.flat() 方法的 polyfill,但是,在检查循环元素是一个数组并且需要进一步展平之后,我在调用函数本身时遇到了问题.当编写非原型代码时,扁平化是正确的,但是当我尝试创建原型函数时,我无法获得扁平化数组。我很确定问题与 'this' 关键字有关。请看看我的代码。

这是代码

let arrayFlat = [1, 2, 3, [4, 5, 6, [7, 8, [9]], 10, [11, 12]], [13, [14, 15]]];

const flatArray = (array) => {
  let output = [];
  const flatten = (array) => {
    for (let i = 0; i < array.length; i++) {
      if (Array.isArray(array[i])) {
        flatten(array[i]);
      } else {
        output.push(array[i]);
      }
    }
    return output;
  };
  return flatten(array);
};

Array.prototype.myFlat = function () {
  let output = [];
  for (let i = 0; i < this.length; i++) {
    if (Array.isArray(this[i])) {
      console.log(this[i]);
      this[i].myFlat();
    } else {
      output.push(this[i]);
    }
  }
  return output;
};

在您的第一段代码中,您创建了一个 output 数组。当您递归调用 flatten 时,代码总是推送到完全相同的 output 数组,该数组位于 flatten 的闭包中。然后一旦一切都完成了,你 return 那个数组。

在第二个代码中,每次递归时都会创建一个新数组。每次递归都会创建一个数组,展平自身,然后 return 那个新数组。但是 return 值被忽略了,所以这些值不会出现在任何地方。

你有几个选择

  1. 使代码与您的第一个代码基本相同,具有一个用于执行递归的内部函数,以及一个供所有人使用的闭包变量:
Array.prototype.myFlat = function () {
  let output = [];
  const flatten = (array) => {
    for (let i = 0; i < array.length; i++) {
      if (Array.isArray(array[i])) {
        flatten(array[i]);
      } else {
        output.push(array[i]);
      }
    }
    return output;
  };
  return flatten(this);
}
  1. 递归时将输出数组作为参数传递:
//                                 VVVVVV--- added parameter
Array.prototype.myFlat = function (output = []) {
  for (let i = 0; i < this.length; i++) {
    if (Array.isArray(this[i])) {
      this[i].myFlat(output); // <---- forward the array along
    } else {
      output.push(this[i]);
    }
  }
  return output;
};
  1. 继续使用单独的数组,然后在展开堆栈时将它们合并在一起:
Array.prototype.myFlat = function () {
  let output = [];
  for (let i = 0; i < this.length; i++) {
    if (Array.isArray(this[i])) {
      output.push(...this[i].myFlat()); // <---- added output.push
    } else {
      output.push(this[i]);
    }
  }
  return output;
};

我强烈支持保持 类 尽可能精简,尽可能包装功能接口 -

function myFlat(t) {
  return Array.isArray(t)
    ? t.reduce((r, v) => r.concat(myFlat(v)), [])
    : [t]
}

Array.prototype.myFlat = function() { return myFlat(this) }

console.log([1,[2,[3],4],[[5]],6,[[[7]]]].myFlat())
// [ 1, 2, 3, 4, 5, 6, 7 ]