Array.push和Array.concat

今天看到了一道题:

已知数据格式,实现一个函数 fn 找出链条中所有的父级 id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const list = [{
id: '1',
name: 'test1',
children: [
{
id: '11',
name: 'test11',
children: [
{
id: '111',
name: 'test111'
},
{
id: '112',
name: 'test112'
}
]

},
{
id: '12',
name: 'test12',
children: [
{
id: '121',
name: 'test121'
},
{
id: '122',
name: 'test122'
}
]
}
]
}];
const id = '112'
const fn = (value) => {
...
}
fn(id, list) // 输出 [1, 11, 112]

先给出答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fn(id, list){
var res = []
function dfs(list, temp = []){
for(const node of list){
if(node.id === id){
res = temp.concat(node.id)
return
} else if(node.children){
dfs(node.children, temp.concat(node.id))
}
}
}
dfs(list)
return res
}

而我最开始的解法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function fn(id, list){
var res = []
function dfs(list, temp = []){
for(const node of list){
if(node.id === id){
// 注意不能直接 res = temp.push(node.id) 因为push方法返回新数组的长度
temp.push(node.id)
res = temp
return
} else if(node.children){
temp.push(node.id)
dfs(node.children, temp)
}
}
}
dfs(list)
return res
}

然而这个解法得不到正确答案

这是由于 Array.push()会改变自身的数组,而Array.concat()不会改变自身的数组。在正确解法中,使用concat方法去传参,并不会影响自身数组,因此在回溯时,得到的还是未被错误路径污染的数组。而用push方法,会改变自身的数组,因此回溯时数组已经被污染了,而且temp的后续修改也会影响到res

Array.push()Array.concat()区别

  • concat不会改变自身数组
  • push会改变自身数组
  • 在push中传入一个数组,该数组会成为原数组的一个元素。
  • push方法返回的是新数组的长度
  • concat返回新数组