递归javascript_使用freeCodeCamp挑战解释了JavaScript中的递归

递归javascript

In this article I will touch on a few important ideas to help you understand Recursion in JavaScript. I’m not going to give a full definition here, but you can take a look at what Wikipedia has to say.

在本文中,我将介绍一些重要的想法,以帮助您了解JavaScript中的递归。 我不会在这里给出完整的定义,但是您可以看看Wikipedia怎么说 。

Let’s agree for the purpose of this article that we are trying to solve a problem by using a function that will then call itself.

出于本文的目的,让我们同意我们正在尝试通过使用一个将自身调用的函数来解决问题。

挑战 (The Challenge)

At the end of the Javascript Algorithms and Data Structures — Basic Javascript section on freeCodeCamp, you run into an interesting problem: ‘Use Recursion to Create a Range of Numbers’, where the instructions are as follows:

在freeCodeCamp上的Javascript算法和数据结构— Basic Javascript部分的最后 ,您遇到了一个有趣的问题:“使用递归创建数字范围”,其说明如下:

We have defined a function named rangeOfNumbers with two parameters. The function should return an array of integers which begins with a number represented by the startNum parameter and ends with a number represented by the endNum parameter. The starting number will always be less than or equal to the ending number. Your function must use recursion by calling itself and not use loops of any kind. It should also work for cases where both startNum and endNum are the same.
我们定义了一个带有两个参数的名为rangeOfNumbers的函数。 该函数应返回一个整数数组,该数组以startNum参数表示的数字开头,以endNum参数表示的数字结尾。 起始编号将始终小于或等于终止编号。 您的函数必须通过调用自身来使用递归,而不能使用任何形式的循环。 它还适用于startNum和endNum相同的情况。

Sounds simple enough – if you were to run rangeOfNumbers(1, 5) it should return [1, 2, 3, 4, 5].

听起来很简单–如果要运行rangeOfNumbers(1,5),它应该返回[1、2、3、4、5]。

If you’re like me, you can sort of intuit the answer based on the previous example in this section. But it might still be a bit unclear how this all works.

如果您像我一样,可以根据本节中的上一个示例来直观地回答问题。 但这可能还不清楚。

Spoiler alert: you'll find an answer immediately below. But this isn’t much of a spoiler since the answer is easy enough to find on the internet.

剧透警报:您会在下面立即找到答案。 但这并不会破坏太多,因为答案很容易在互联网上找到。

我的解决方案 (My Solution)

It’s very probable that you can read through the code and understand that when it gets down to its base case it will return whatever the startNum is into the array. Then it will keep pushing the other values onto that array until it’s done with all of its recursive calls.

您很可能可以通读代码并了解其基本情况 ,它将返回数组中的startNum。 然后它将继续将其他值推入该数组,直到完成所有递归调用为止。

function rangeOfNumbers(startNum, endNum) {if (startNum === endNum) {return [startNum];} else {       const numbers = rangeOfNumbers(startNum, endNum - 1);numbers.push(endNum);return numbers;}
}

What I found to be tricky was understanding exactly how the call stack was working and how my values were being returned.

我发现棘手的是确切地了解调用堆栈如何工作以及如何返回我的值。

So let's break down how this function will return its final value.

因此,让我们分解一下此函数将如何返回其最终值。

调用堆栈 (The Call Stack)

The first thing to understand is how the call stack works. I will refer you to Mozilla Developer Network's explanation:

首先要了解的是调用堆栈如何工作。 我将向您介绍Mozilla开发人员网络的解释 :

When a script calls a function, the interpreter adds it to the call stack and then starts carrying out the function.

当脚本调用函数时,解释器将其添加到调用堆栈中,然后开始执行该函数。

When a script calls a function, the interpreter adds it to the call stack and then starts carrying out the function.

当脚本调用函数时,解释器将其添加到调用堆栈中,然后开始执行该函数。

Any functions that are called by that function are added to the call stack further up, and run where their calls are reached.

该函数调用的所有函数都会进一步添加到调用堆栈中,并在到达其调用的位置运行。

Any functions that are called by that function are added to the call stack further up, and run where their calls are reached.

该函数调用的所有函数都会进一步添加到调用堆栈中,并在到达其调用的位置运行。

Using this explanation, let’s run the code above using rangeOfNumbers(1,5).

使用此说明,让我们使用rangeOfNumbers(1,5)运行上面的代码

First the rangeOfNumbers — Execution Context is created and executed with the following values:

首先,使用以下值创建并执行rangeOfNumbers —执行上下文:

So we have added an unresolved rangeOfNumbers(1,5) function call to our stack. Then we move on to create the execution for rangeOfNumbers(1,4), and so on and so forth, adding each one of these calls to our stack until we will finally resolve a function call. Then the interpreter will take that function off the stack and move on to the next one.

因此,我们向堆栈中添加了一个未解决的rangeOfNumbers(1,5)函数调用。 然后,我们继续为rangeOfNumbers(1,4)创建执行程序, 依此类推依次类推,将这些调用中的每一个添加到堆栈中,直到最终解决函数调用为止。 然后,解释器将从堆栈中删除该函数,然后移至下一个函数。

检查我们的通话堆栈 (Examining Our Call Stack)

So our stack will end up looking like this:

因此,我们的堆栈最终将如下所示:

rangeOfNumbers(1,1)
rangeOfNumbers(1,2)
rangeOfNumbers(1,3)
rangeOfNumbers(1,4)
rangeOfNumbers(1,5)

rangeOfNumbers(1,1) will be the last one in our stack because, finally, this call will RETURN a value allowing us to move on to our next function in the stack.

rangeOfNumbers(1,1)将是堆栈中的最后一个,因为最后,此调用将返回一个值,使我们可以继续执行堆栈中的下一个函数。

rangeOfNumbers(1,1) return value is [1], as we had assumed it would be since it is our base case. Now we pop rangeOfNumbers(1,1) off our stack, and go back to where rangeOfNumbers(1,2) left off…

rangeOfNumbers(1,1)的返回值是[1],正如我们已经假定的那样,因为它是我们的基本情况。 现在,我们从堆栈中弹出rangeOfNumbers(1,1) ,然后返回到距离rangeOfNumbers(1,2)不远的地方…

var numbers = rangeOfNumbers(1,2) // returns an array of [1]

Numbers is no longer undefined and the next step is to push the endNum, which is 2, into the numbers array. This gives us [1,2] in numbers, and now we return the value.

Numbers不再是未定义的 ,下一步是将为 2的endNum推入numbers数组。 这样就给了我们[1,2]个数字,现在我们返回了值。

numbers.push(endNum) //numbers now holds an array of [1,2]
return numbers; // ends our function and returns [1,2]

分解棘手的部分 (Breaking Down The Tricky Part)

So we pop off rangeOfNumbers(1,2) which had a return value of [1,2]. Let’s resume with the next call in our stack rangeOfNumbers(1,3). Numbers is currently [1,2] because that is the return value of rangeOfNumbers(1,2). This is what we had plugged in when we called rangeOfNumbers(1,3) because, again, the 3 is subtracted by 1, that is rangeOfNumbers(1,2), which as we said returns [1,2].

因此,我们弹出rangeOfNumbers(1,2) ,其返回值为[1,2]。 让我们从堆栈rangeOfNumbers(1,3)中的下一个调用继续 Numbers当前为[1,2],因为那是rangeOfNumbers(1,2)的返回值 这就是我们在调用rangeOfNumbers(1,3)时插入的内容,因为再次将3减去1,即rangeOfNumbers(1,2) ,正如我们所说的返回[1,2]。

Got it? Great! If you don’t get it, reread this paragraph, because this is the trickiest part to understand.

得到它了? 大! 如果不理解,请重新阅读本段,因为这是最难理解的部分。

If you’re up to speed let’s continue. If that part above clicked the rest should feel pretty easy.

如果您要加快速度,那就继续吧。 如果单击上方的那部分,其余部分应该会很容易。

Back to rangeOfNumbers(1,3): the numbers array is currently [1,2], so we push the endNum which is 3. Now we have [1,2,3] and we return this value again. We remove rangeOfNumbers(1,3) from our stack which returned the value [1,2,3].

返回rangeOfNumbers(1,3) :numbers数组当前为[1,2],因此我们将endNum推为3。现在我们有了[1,2,3],然后再次返回该值。 我们从返回值[1,2,3]的堆栈中删除rangeOfNumbers(1,3)

How did we get rangeOfNumbers(1,3)? That’s right, from when we called rangeOfNumbers(1,4) and endNumb -1, that is → 3, and we know that rangeOfNumbers(1,3) gives us the return value of [1,2,3] which is exactly what we have in our array.

我们如何获得rangeOfNumbers(1,3)? 没错,从我们调用rangeOfNumbers(1,4)和endNumb -1开始,即→3,并且我们知道rangeOfNumbers(1,3)为我们提供了[1,2,3]的返回值我们有我们的阵列。

Now we push the endNum (also known as 4) onto the numbers array, giving us [1,2,3,4] and we return this value. Let’s again remove this function call from the stack since it gave us what we wanted.

现在我们将endNum(也称为4)压入数字数组,得到[1,2,3,4]并返回此值。 让我们再次从堆栈中删除此函数调用,因为它满足了我们的需求。

汇集全部 (Bringing it all together )

Now for the call that started it all: rangeOfNumbers(1,5). The first step we do is determine what value we have in numbers. When put in rangeOfNumbers(1,4) we get, as we said before, [1,2,3,4]. So we can now push our endNum 5 into the array and get [1,2,3,4,5] which we will return, and our stack is now empty with our last call.

现在开始所有的调用: rangeOfNumbers(1,5) 。 我们要做的第一步是确定数字所具有的价值。 如前所述,rangeOfNumbers(1,4)放入[1,2,3,4]。 因此,我们现在可以将endNum 5推入数组并获取[1,2,3,4,5],我们将返回它,并且我们的堆栈在上一次调用时为空。

So let’s quickly review which returned what value and in what order.

因此,让我们快速回顾一下哪个返回了什么值以及返回了什么顺序。

rangeOfNumbers(1,1) → returns [1]
rangeOfNumbers(1,2) → returns [1,2]
rangeOfNumbers(1,3) → returns [1,2,3]
rangeOfNumbers(1,4) → returns [1,2,3,4]
rangeOfNumbers(1,5) → returns [1,2,3,4,5]

If this is still confusing, firstly I understand – it’s a confusing topic. Next I would recommend typing in your code into this great tool: http://www.pythontutor.com/javascript.html

如果这仍然令人困惑,那么我首先要理解-这是一个令人困惑的话题。 接下来,我建议您在此出色的工具中输入代码: http : //www.pythontutor.com/javascript.html

This is all able to work because we started with a small base case and we essentially built our way back up. Each time our return value is a bit bigger than it was on its previous call, much like if you were to perform this same operation with a for loop.

这一切都是可行的,因为我们从一个小的基本案例入手,并且基本上建立了自己的备份方式。 每次我们的返回值都比上一次调用大,就像您要使用for循环执行相同的操作一样。

Have any questions? Feel free to ask me on Twitter: @NehemiahKiv

有什么问题吗? 随时在Twitter上问我: @NehemiahK iv

翻译自: https://www.freecodecamp.org/news/learn-recursion-in-javascript-by-example/

递归javascript

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

入库成本与目标成本对比报表中我学到的东西

1、SQL方面: (1)、用DECODE函数解决除数为零的情况 具体语法: DECODE(参数,0,1,参数) ->DECODE(TAB1.A8,0,1,TAB1.A8) &#xff08…

J - Borg Maze

J - Borg Maze 思路&#xff1a;bfs最小生成树。#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 110 using namespace std; int fa[MAXN]; struct nond{int x,y,z; }v[MAXN*MAXN]; s…

1095. 山脉数组中查找目标值

1095. 山脉数组中查找目标值 &#xff08;这是一个 交互式问题 &#xff09; 给你一个 山脉数组 mountainArr&#xff0c;请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 index 值。 如果不存在这样的下标 index&#xff0c;就请返回 -1。 何为山脉数组…

【小摘抄】关于C++11下 string各类用法(持续更新)

http://blog.csdn.net/autocyz/article/details/42391155 提供了最简单的详解 下列对本人近期开发中的一些心得体会进行摘抄 1.string按照字符进行截取 示例代码&#xff1a; string teststring "#12313#kajlkfdsa";//通讯消息示例&#xff0c;结合string的内置函数…

sql综合练习题

一、表关系 年级表&#xff1a;class_grade create table class_grade(gid int primary key auto_increment,gname varchar(20) not null); insert into class_grade(gname) values(一年级),(二年级),(三年级); 班级表&#xff1a;class create table class(cid int primary ke…

javascript原型_在JavaScript中冻结原型时会发生什么

javascript原型Have you wondered what happens when you freeze the prototype of an object? Lets find out together.您是否想过冻结对象的原型时会发生什么&#xff1f; 让我们一起找出答案。 对象 (Objects) In JavaScript, objects are dynamic collections of propert…

迟来的2017总结

明天就是年后第一天上班了&#xff08;过年期间请了6天假&#xff09;&#xff0c; 打算今天写一下2017的总结&#xff0c;本来还想写2018的愿景的&#xff0c;不过想想还是算了&#xff0c;现在没什么想法&#xff0c;不想敷衍了事。 先贴一个2017的提升计划&#xff1a; http…

tomcat启动卡住

新部署的项目启动tomcat后一直停在org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.16&#xff0c;卡在了org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/opt/tomcat/web…

怎样准备阿里技术面试_如何准备技术面试

怎样准备阿里技术面试In June 2020 I watched an inspiring talk by Anthony D. Mays, a technical coach and founder at Morgan Latimerco. He came on a Facebook Developer Circles Benin live session and talked about how to prepare for a technical interview. 2020年…

通过一个简单例子理解 RecyclerView.ItemDecoration

一、前言 RecyclerView 是从5.0推出的 MD 风格的控件。RecyclerView 之前有 ListView、GridView&#xff0c;但是功能很有限&#xff0c;例如 ListView 只能实现垂直方向上的滑动等。但是存在则合理&#xff0c;ListView 却没有被官方标记为 Deprecated&#xff0c;有兴趣的同学…

Entity Framework Logging and Intercepting Database Operations (EF6 Onwards)

参考官方文档&#xff1a;https://msdn.microsoft.com/en-us/library/dn469464(vvs.113).aspx转载于:https://www.cnblogs.com/liandy0906/p/8473110.html

面试题 17.14. 最小K个数

面试题 17.14. 最小K个数 设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 示例&#xff1a; 输入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 输出&#xff1a; [1,2,3,4] 提示&#xff1a; 0 < len(arr) < 1000000 < k < min(1…

这是您现在可以免费获得的115张Coursera证书(在冠状病毒大流行期间)

At the end of March, the world’s largest Massive Open Online Course provider Coursera announced that they are offering 100 free courses in response to the impact of the COVID-19 pandemic. 3月底&#xff0c;全球最大的大规模在线公开课程提供商Coursera 宣布 &a…

由浅入深理解----java反射技术

java反射机制详解 java反射机制是在运行状态下&#xff0c;对任意一个类可以获取该类的属性和方法&#xff0c;对任意一个对象可以调用其属性和方法。这种动态的获取信息和调用对象的方法的功能称为java的反射机制 class<?>类&#xff0c;在java.lang包下面&#xff0c;…

【VMware vSAN 6.6】5.5.Update Manager:vSAN硬件服务器解决方案

目录 1. 简介 1.1.适用于HCI的企业级存储2. 体系结构 2.1.带有本地存储的服务器2.2.存储控制器虚拟系统套装的缺点2.3.vSAN在vSphere Hypervisor中自带2.4.集群类型2.5.硬件部署选项3. 启用vSAN 3.1.启用vSAN3.2.轻松安装3.3.主动测试4. 可用性 4.1.对象和组件安置4.2.重新构建…

5848. 树上的操作

给你一棵 n 个节点的树&#xff0c;编号从 0 到 n - 1 &#xff0c;以父节点数组 parent 的形式给出&#xff0c;其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点&#xff0c;所以 parent[0] -1 &#xff0c;因为它没有父节点。你想要设计一个数据结构实现树里面…

了解如何通过Python使用SQLite数据库

SQLite is a very easy to use database engine included with Python. SQLite is open source and is a great database for smaller projects, hobby projects, or testing and development.SQLite是Python附带的非常易于使用的数据库引擎。 SQLite是开源的&#xff0c;是用于…

32位JDK和64位JDK

32位和64位系统在计算机领域中常常提及&#xff0c;但是仍然很多人不知道32位和64位的区别&#xff0c;所以本人在网上整理了一些资料&#xff0c;并希望可以与大家一起分享。对于32位和64位之分&#xff0c;本文将分别从处理器&#xff0c;操作系统&#xff0c;JVM进行讲解。 …

中小企业如何选择OA协同办公产品?最全的对比都在这里了

对于中小企业来说&#xff0c;传统的OA 产品&#xff0c;如泛微、蓝凌、致远、华天动力等存在价格高、使用成本高、二次开发难等特点&#xff0c;并不适合企业的协同管理。 国内OA市场也出现了一批轻便、低价的OA产品&#xff0c;本文针对以下几款适合中小企业的OA产品在功能、…

python缓冲区_如何在Python中使用Google的协议缓冲区

python缓冲区When people who speak different languages get together and talk, they try to use a language that everyone in the group understands. 当说不同语言的人聚在一起聊天时&#xff0c;他们会尝试使用小组中每个人都能理解的语言。 To achieve this, everyone …