2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								---
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								id: 5cd9a70215d3c4e65518328f
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								title: 使用递归创建一个倒计时
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								challengeType: 1
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								forumTopicId: 305925
							 
						 
					
						
							
								
									
										
										
										
											2021-01-13 03:31:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								dashedName: use-recursion-to-create-a-countdown
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								---
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# --description--
  
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								在上一个[挑战 ](/learn/javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion ),学习了怎样用递归来代替 `for`  循环。 现在来学习一个更复杂的函数,函数返回一个从 `1`  到传递给函数的指定数字的连续数字数组。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								正如上一个挑战提到的,会有一个 < dfn > base case< / dfn > 。 base case 告诉递归函数什么时候不在需要调用其自身。 这是简单 情况,返回得到的值。 还有 < dfn > recursive call< / dfn > ,继续用不同的参数调用自身。 如果函数无误,一直执行直到 base case 为止。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								比如,如果想写一个递归函数,返回一个数字 `1`  到 `n`  的连续数组。 这个函数需要接收一个参数 `n`  代表最终数字。 然后会持续的调用自身,传入一个比 `n`  更小的值一直到传入的值是 `1`  为止。 函数如下:
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```javascript
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function countup(n) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (n <  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } else {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const countArray = countup(n - 1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    countArray.push(n);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return countArray;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								console.log(countup(5));
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								值 `[1, 2, 3, 4, 5]`  将显示在控制台中。
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								起初,这似乎是违反直觉的,因为 `n`  的值*递减*,但是最终数组中的值却*递增*。 之所以发生这种情况,是因为在递归调用返回之后,才调用 push。 在将 `n`  pushed 进数组时,`countup(n - 1)`  已经调用赋值成功并返回了 `[1, 2, ..., n - 1]` 。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# --instructions--
  
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								已经定义了一个函数 `countdown` ,函数有一个参数(`n` )。 函数应该基于参数 `n`  递归调用返回 `n`  到 `1`  的连续数字的数组。 如果函数以小于 1 的参数调用,函数应该返回空数组。 比如,用 `n = 5`  调用函数应该返回数组 `[5, 4, 3, 2, 1]` 。 函数必需使用递归函数调用自身,不能使用任何形式的循环。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# --hints--
  
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`countdown(-1)`  应该返回一个空数组。 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								assert.isEmpty(countdown(-1));
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`countdown(10)`  应该返回 `[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]` 。 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								assert.deepStrictEqual(countdown(10), [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								`countdown(5)`  应该返回 `[5, 4, 3, 2, 1]` 。 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								assert.deepStrictEqual(countdown(5), [5, 4, 3, 2, 1]);
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								代码不能包含任意形式的循环(`for` 、`while`  或者高阶函数如:`forEach` 、`map` 、`filter`  以及 `reduce` )。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
									
										
										
										
											2021-02-06 04:42:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								assert(
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 16:18:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  !code.match(/for|while|forEach|map|filter|reduce/g)
							 
						 
					
						
							
								
									
										
										
										
											2021-02-06 04:42:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								);
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 21:20:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								应该用递归解决这个问题。
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
									
										
										
										
											2021-02-06 04:42:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								assert(
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 16:18:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  countdown.toString().match(/countdown\s*\(.+\)/)
							 
						 
					
						
							
								
									
										
										
										
											2021-02-06 04:42:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								);
							 
						 
					
						
							
								
									
										
										
										
											2020-04-29 18:29:13 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-13 03:31:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# --seed--
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## --seed-contents--
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Only change code below this line
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function countdown(n){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Only change code above this line
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-16 00:37:30 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# --solutions--
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-13 03:31:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function countdown(n){
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   return n <  1  ?  [ ]  :  [ n ] . concat ( countdown ( n  -  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```