如何在 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 值被忽略了,所以这些值不会出现在任何地方。
你有几个选择
- 使代码与您的第一个代码基本相同,具有一个用于执行递归的内部函数,以及一个供所有人使用的闭包变量:
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);
}
- 递归时将输出数组作为参数传递:
// 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;
};
- 继续使用单独的数组,然后在展开堆栈时将它们合并在一起:
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 ]
我正在创建一个 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 值被忽略了,所以这些值不会出现在任何地方。
你有几个选择
- 使代码与您的第一个代码基本相同,具有一个用于执行递归的内部函数,以及一个供所有人使用的闭包变量:
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);
}
- 递归时将输出数组作为参数传递:
// 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;
};
- 继续使用单独的数组,然后在展开堆栈时将它们合并在一起:
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 ]