1
00:00:02,100 --> 00:00:04,340
So recursion can save us code,

2
00:00:04,380 --> 00:00:08,850
it can also solve problems which we couldn't solve with a for loop

3
00:00:08,880 --> 00:00:18,890
Let's say we have a constant, myself and I'm an object with a name, Max and with some friends and friends

4
00:00:18,900 --> 00:00:21,330
could be an array right because it's a list of friends.

5
00:00:21,330 --> 00:00:25,250
Now every friend also is an object, an object with a name,

6
00:00:25,350 --> 00:00:30,240
for example Manuel and maybe also some friends,

7
00:00:30,240 --> 00:00:36,980
so here a nested array. Here we could have some fictional friend, Chris

8
00:00:37,260 --> 00:00:41,440
and there we got no friends because Chris doesn't have friends,

9
00:00:41,460 --> 00:00:42,710
whatever.

10
00:00:42,730 --> 00:00:47,550
Now i also have another friend and that could be Julia

11
00:00:48,070 --> 00:00:56,410
and let's say she also has no friends but what we do have here therefore is a bunch of objects which

12
00:00:56,470 --> 00:01:03,130
all have the same structure, a name and potentially some friends and they can be nested as deep as you

13
00:01:03,130 --> 00:01:03,640
want,

14
00:01:03,640 --> 00:01:05,880
Chris could have friends,

15
00:01:05,980 --> 00:01:08,080
Julia could have friends.

16
00:01:08,080 --> 00:01:12,460
So we don't know how many levels of nesting we have here

17
00:01:12,460 --> 00:01:17,420
and that's not just a fictional problem, you could encounter this in many applications you're writing.

18
00:01:17,710 --> 00:01:23,230
Let's say you're building an application like Dropbox where you want to render a folder structure, well

19
00:01:23,320 --> 00:01:25,750
every folder could have subfolders,

20
00:01:25,750 --> 00:01:29,860
so then you would have exactly this data structure behind the scenes.

21
00:01:29,860 --> 00:01:35,470
You don't know how many folders the user of your application is going to create but you will have the

22
00:01:35,470 --> 00:01:39,780
same kind of object just nested at different levels,

23
00:01:39,790 --> 00:01:43,500
you don't know how many levels of nesting you'll need.

24
00:01:43,600 --> 00:01:49,960
So therefore, we could have a scenario like this where we know we have the same kind of objects nested

25
00:01:49,960 --> 00:01:53,130
into each other in the end but we don't know how many.

26
00:01:53,230 --> 00:02:02,530
Now if we wanted a function, print friend names, then we can't use a for loop here to loop through all

27
00:02:02,530 --> 00:02:10,850
the friends because here of course, I could expect to get a person as an input and I could then try to

28
00:02:10,850 --> 00:02:21,450
go through all friends of person.friends but now as you learned, for Max for example, I have Manuel

29
00:02:21,480 --> 00:02:30,460
who also has friends, so I would need a nested for loop here, friends, friends of

30
00:02:33,810 --> 00:02:35,970
friends.friends,

31
00:02:36,000 --> 00:02:40,850
so this is now for nested friends but for one, not every person has friends,

32
00:02:40,860 --> 00:02:41,730
that's a problem

33
00:02:41,730 --> 00:02:45,870
so I maybe tried to loop through friends which aren't there, like in the case of Julia

34
00:02:46,410 --> 00:02:52,170
and even if a person has friends like Manuel does, then I don't know if I need another nested loop

35
00:02:52,200 --> 00:02:56,960
because here, the friends of Manuel, in this case Chris also might have friends

36
00:02:57,150 --> 00:03:03,660
and even if I would know how many levels of nesting I have which I don't, we would have tons of nested

37
00:03:03,660 --> 00:03:07,290
for loops which is pretty hard to read code.

38
00:03:07,440 --> 00:03:15,600
So in the best case, we know how many loops we need, then it's hard to read, in the worst case which will

39
00:03:15,780 --> 00:03:21,710
often be the case, you don't know how many levels of nesting you need because that data might not be hard

40
00:03:21,710 --> 00:03:25,530
coded by you but you might be downloading that from some database,

41
00:03:25,580 --> 00:03:31,890
maybe it then was created by users of your application, so at the point of time you're writing your code,

42
00:03:32,130 --> 00:03:36,240
you can't know how many levels of nesting you'll have,

43
00:03:36,240 --> 00:03:38,600
so this then even isn't an option,

44
00:03:38,610 --> 00:03:41,580
this is where recursion can really shine.

45
00:03:41,880 --> 00:03:48,040
Here we could create a collected names constant or variable,

46
00:03:48,080 --> 00:03:49,830
now we can add a for loop in here,

47
00:03:49,850 --> 00:03:55,280
we need one where we go through all friends of person.friends,

48
00:03:58,300 --> 00:04:03,330
so if I passed in my self here, I would access the friends property and now go through this array

49
00:04:04,480 --> 00:04:14,570
and add the friends to the collected names, to be precise friends.name and then here, we could return

50
00:04:14,680 --> 00:04:15,890
the collected names.

51
00:04:15,890 --> 00:04:17,810
Now we don't use recursion yet,

52
00:04:17,990 --> 00:04:19,460
let's still see what we get here

53
00:04:19,460 --> 00:04:27,140
If I console log the result of print friend names for myself which is that constant here. If we do that

54
00:04:27,140 --> 00:04:35,150
and we save that and we reload, I see Manuel and Julia because these are the direct friends of myself.

55
00:04:35,150 --> 00:04:42,410
Now we want to use recursion to go through all nested friends friends as well. For this inside of the

56
00:04:42,410 --> 00:04:52,460
for loop, instead of just pushing the friend names here, we can call print friend names again and we pass

57
00:04:52,460 --> 00:04:59,360
in friend because print friend names expects a person, so it expects an object with a friends key and

58
00:04:59,360 --> 00:05:03,270
when we go through my friends here, we get such objects.

59
00:05:03,470 --> 00:05:10,250
Now maybe they don't all have friends though, this friends key might not exist for every nested object.

60
00:05:10,490 --> 00:05:17,360
So inside of print friend names, we should add an if check and check if person.friends is a thing

61
00:05:17,840 --> 00:05:23,660
and if it's falsy, hence the exclamation mark at the beginning, so if we don't have a truthy value for

62
00:05:23,660 --> 00:05:31,010
the friends key, so if it's undefined effectively like it is for Julia or for Chris, then we just return

63
00:05:31,010 --> 00:05:32,710
here, to be precise

64
00:05:32,720 --> 00:05:37,370
we return an empty array because then this person has no friends,

65
00:05:37,430 --> 00:05:42,580
otherwise we make it to the for loop where we go through all friends of friends.

66
00:05:42,740 --> 00:05:50,750
Now i expect print friend names or maybe we should call it get friend name therefore to return a

67
00:05:50,750 --> 00:05:52,330
list of friends.

68
00:05:52,370 --> 00:05:55,430
So here actually, what gets returned here is always an array,

69
00:05:55,490 --> 00:06:05,300
either an empty one or one of the names. For that we should still push every friend.name to our collected

70
00:06:05,300 --> 00:06:06,130
names

71
00:06:06,290 --> 00:06:11,960
and then in the end, return collected names which also is an array, so that get friend names always returns

72
00:06:11,960 --> 00:06:13,600
an array.

73
00:06:13,610 --> 00:06:19,820
Now what do we do with that return value of get friend names inside of get friend names which is our

74
00:06:19,820 --> 00:06:26,440
recursive call? Well in the end, that will be all the names of the friend we're looking at here in this

75
00:06:26,440 --> 00:06:33,720
for/of loop and we want to add these names to the collected names array we're merging here. So here

76
00:06:33,810 --> 00:06:40,680
we can simply say collectedNames.push and now however we have to be careful because that will return

77
00:06:40,680 --> 00:06:45,330
an array and I don't want to add that array as a nested array to our array here,

78
00:06:45,360 --> 00:06:51,270
instead we can use the spread operator to spread this into multiple individual pieces and since push

79
00:06:51,270 --> 00:06:57,150
takes multiple arguments, as many as we want, these will then be added one by one to our collected names

80
00:06:57,150 --> 00:06:57,810
array

81
00:06:58,110 --> 00:07:05,550
and with that if we also update the name down there to avoid errors, if we save that and reload, we get

82
00:07:05,550 --> 00:07:12,800
a list where Manuel, Chris and Julia are included and these are my friends here,

83
00:07:12,800 --> 00:07:13,350
Manuel,

84
00:07:13,350 --> 00:07:14,720
Chris and Julia

85
00:07:14,720 --> 00:07:24,920
and if Chris also had some friends where we again have a name, Harry, and maybe another friend where we

86
00:07:24,920 --> 00:07:29,180
also have a name, Amelia,

87
00:07:29,490 --> 00:07:32,970
then these two names will also be included if we reload,

88
00:07:32,970 --> 00:07:41,400
here they are, because we now have recursion to go through that data structure here. And you see how

89
00:07:41,400 --> 00:07:42,760
flexible this approach is,

90
00:07:42,810 --> 00:07:48,620
we can easily add more friends and deeper and deeper nesting of friends and due to the way how this

91
00:07:48,710 --> 00:07:50,950
function is written and the logic we have in there,

92
00:07:51,000 --> 00:07:58,440
this will go through as many levels of nesting as we need because it doesn't care, it calls itself and

93
00:07:58,440 --> 00:08:05,190
dives into the friends until there are no more friends for a given person and then it returns and returns

94
00:08:05,220 --> 00:08:12,530
and returns until it's done with the outermost function call where then it returns the overall value.

95
00:08:12,540 --> 00:08:19,140
Now recursion can be difficult to wrap your head around but the developer tools can help you just as i showed

96
00:08:19,140 --> 00:08:25,380
you, add some breakpoints and carefully step through the execution to get a feeling for where you are

97
00:08:25,380 --> 00:08:32,790
at and how it works and then the idea is that you have a function which calls itself and then uses the

98
00:08:32,850 --> 00:08:36,450
return value of that internal function call.

99
00:08:36,480 --> 00:08:39,500
You always need some exit condition,

100
00:08:39,750 --> 00:08:45,480
otherwise you'll get an infinite call stack and this will break your app and throw an error

101
00:08:45,480 --> 00:08:52,320
but as long as you have that and you're sure that it can be met, you have a powerful tool to save

102
00:08:52,310 --> 00:08:58,840
code as we did here or to go through data structures which you couldn't really go through otherwise.
