请考虑以下代码。
array.forEach
来电的代码。var data = ['a', 'b', 'c'];
var all_combinations = [];
function recursiveGetAllCombinations(data_cursor = 0, combination_being_constructed = []) {
data.forEach(function(element) {
combination_being_constructed[data_cursor] = element;
if(data_cursor == data.length - 1) {
all_combinations.push(combination_being_constructed);
} else {
recursiveGetAllCombinations(data_cursor + 1, combination_being_constructed.slice());
}
});
}
recursiveGetAllCombinations();
console.log(all_combinations);
它console.log
正确的输出(更准确地说,几乎正确的结果,因为有冗余:每个元素重复3次 - 但不应该是这种情况,因为forEach(element)
将element
的值从迭代更改为另一个,显然........
(27) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3)]
0
:
(3) ["a", "a", "c"]
1
:
(3) ["a", "a", "c"]
2
:
(3) ["a", "a", "c"]
3
:
(3) ["a", "b", "c"]
4
:
(3) ["a", "b", "c"]
5
:
(3) ["a", "b", "c"]
6
:
(3) ["a", "c", "c"]
7
:
(3) ["a", "c", "c"]
8
:
(3) ["a", "c", "c"]
9
:
(3) ["b", "a", "c"]
10
:
(3) ["b", "a", "c"]
11
:
(3) ["b", "a", "c"]
12
:
(3) ["b", "b", "c"]
13
:
(3) ["b", "b", "c"]
14
:
(3) ["b", "b", "c"]
15
:
(3) ["b", "c", "c"]
16
:
(3) ["b", "c", "c"]
17
:
(3) ["b", "c", "c"]
18
:
(3) ["c", "a", "c"]
19
:
(3) ["c", "a", "c"]
20
:
(3) ["c", "a", "c"]
21
:
(3) ["c", "b", "c"]
22
:
(3) ["c", "b", "c"]
23
:
(3) ["c", "b", "c"]
24
:
(3) ["c", "c", "c"]
25
:
(3) ["c", "c", "c"]
26
:
(3) ["c", "c", "c"]
length
:
27
for
循环。var data = ['a', 'b', 'c'];
var all_combinations = [];
function recursiveGetAllCombinations(data_cursor = 0, combination_being_constructed = []) {
for(i = 0; i < data.length; i++) {
combination_being_constructed[data_cursor] = data[i];
if(data_cursor == data.length - 1) {
all_combinations.push(combination_being_constructed);
} else {
recursiveGetAllCombinations(data_cursor + 1, combination_being_constructed.slice());
}
}
}
recursiveGetAllCombinations();
console.log(all_combinations);
(3) [Array(3), Array(3), Array(3)]
0
:
(3) ["a", "a", "c"]
1
:
(3) ["a", "a", "c"]
2
:
(3) ["a", "a", "c"]
length
:
3
我有两个问题。
1)首先,为什么带forEach
的代码每个元素显示三次?
2)第二个:为什么两个程序在显示结果方面有所不同?
答案 0 :(得分:2)
问题:
重复使用相同的数组
这是因为在迭代时你不会获取数组的副本。您在递归调用中执行slice
,但这还不够。当您处于最深的递归级别时,首先在数组的最后一个条目中写入“a”,将其推送到结果上,然后在相同的内存位置写入“b”。因此,您实际上更改了已推送的数据,同时又重新添加了它。现在你有两倍相同的结果。放“c”时会发生同样的情况:您更改了之前添加的两个结果。它们都是三个相同的阵列。
所以将slice
(仅)应用于传递给push
方法的参数:
all_combinations.push(combination_being_constructed.slice());
第二个代码不会产生太多结果
这是因为在JavaScript中,如果您没有使用var
,let
或const
关键字明确声明变量,则会声明隐式在全局范围内,因此,在递归函数调用中共享。在最深的递归级别,它迭代到数组的末尾,并且递归树中待处理的所有循环现在也将退出,因为它们都共享相同的i
变量。 / p>
通过在函数作用域(或块作用域)中声明i
来解决此问题。使用:
for (let i = 0; i < data.length; i++) {
一种简单的方法来检测您是否意外地执行此操作是将"use strict";
置于代码文件或函数的顶部,它将引发控制台错误,而不是隐式声明全局范围内的变量。