用 JavaScript 的方式理解递归
栏目: JavaScript · 发布时间: 7年前
内容简介:栈是什么?可以理解是在内存中某一块区域,这个区域比喻成一个箱子,你往箱子里放些东西,这动作就是所以得出结论,我们有个习惯,拿东西是从上面往下拿,最先放下去的东西在箱子的最底下,最后才能拿到。在 JavaScript 中,调用函数时,都会发生压栈行为,遇到含
栈是什么?可以理解是在内存中某一块区域,这个区域比喻成一个箱子,你往箱子里放些东西,这动作就是 压栈 。所以最先放下去的东西在箱子最底下,最后放下去的在箱子最上面。把东西从箱子中拿出来可以理解为**出栈*。
所以得出结论,我们有个习惯,拿东西是从上面往下拿,最先放下去的东西在箱子的最底下,最后才能拿到。
在 JavaScript 中,调用函数时,都会发生压栈行为,遇到含 return 关键字的句子或执行结束后,才会发生出栈(pop)。
来看个例子,这个段代码执行顺序是怎样的?
function `() {
return 'this is fn1'
}
function fn2() {
fn3()
return 'this is fn2'
}
function fn3() {
let arr = ['apple', 'banana', 'orange']
return arr.length
}
function fn() {
fn1()
fn2()
console.log('All fn are done')
}
fn()
复制代码
上面发生了一系列压栈出栈的行为:
- 首先,一开始栈(箱子)是空的
- 函数
fn执行,fn先压栈,放在栈(箱子)最底下 - 在函数 fn 内部,先执行函数
fn1,fn1压栈在fn上面 - 函数
fn1执行,遇到return关键字,返回this is fn1,fn1出栈,箱子里现在只剩下fn - 回到
fn内部,fn1执行完后,函数fn2开始执行,fn2压栈,但是在fn2内部,遇到fn3,开始执行fn3,所以fn3压栈 - 此时栈中从下往上顺序为:
fn3<=fn2<=fn,fn在最底下 - 以此类推,函数
fn3内部遇到return关键字的句子,fn3执行完结束后出栈,回到函数fn2中 ,fn2也是遇到return关键字,继续出栈。 - 现在栈中只有
fn了,回到函数fn中,执行console.log('All fn are done') 语句后,fn出栈。 - 现在栈中又为空了。
上面步骤容易把人绕晕,下面是流程图:
再看下在 chrome 浏览器环境下执行:
3. 递归
先看下简单的 JavaScript 递归
function sumRange(num) {
if (num === 1) return 1;
return num + sumRange(num - 1)
}
sumRange(3) // 6
复制代码
上面代码执行顺序:
- 函数
sumRange(3)执行,sumRange(3)压栈,遇到return关键字,但这里还马上不能出栈,因为调用了sumRange(num - 1)即sumRange(2) - 所以,
sumRange(2)压栈,以此类推,sumRange(1)压栈, - 最后,
sumRange(1)出栈返回 1,sumRange(2)出栈,返回 2,sumRange(3)出栈 - 所以
3 + 2 + 1结果为 6
看流程图
所以,递归也是个压栈出栈的过程。
递归可以用非递归表示,下面是上面递归例子等价执行
// for 循环
function multiple(num) {
let total = 1;
for (let i = num; i > 1; i--) {
total *= i
}
return total
}
multiple(3)
复制代码
4. 递归注意点
如果上面例子修改一下,如下:
function multiple(num) {
if (num === 1) console.log(1)
return num * multiple(num - 1)
}
multiple(3) // Error: Maximum call stack size exceeded
复制代码
上面代码第一行没有 return 关键字句子,因为递归没有终止条件,所以会一直压栈,造成内存泄漏。
递归容易出错点
- 没有设置终止点
- 除了递归,其他部分的代码
- 什么时候递归合适
好了,以上就是 JavaScript 方式递归的概念。
下面是练习题。
6. 练习题目
- 写一个函数,接受一串字符串,返回一个字符串,这个字符串是将原来字符串倒过来。
- 写一个函数,接受一串字符串,同时从前后开始拿一位字符对比,如果两个相等,返回
true,如果不等,返回false。 - 编写一个函数,接受一个数组,返回扁平化新数组。
- 编写一个函数,接受一个对象,这个对象值是偶数,则让它们相加,返回这个总值。
- 编写一个函数,接受一个对象,返回一个数组,这个数组包括对象里所有的值是字符串
7. 参考答案
参考1
function reverse(str) {
if(str.length <= 1) return str;
return reverse(str.slice(1)) + str[0];
}
reverse('abc')
复制代码
参考2
function isPalindrome(str){
if(str.length === 1) return true;
if(str.length === 2) return str[0] === str[1];
if(str[0] === str.slice(-1)) return isPalindrome(str.slice(1,-1))
return false;
}
var str = 'abba'
isPalindrome(str)
复制代码
参考3
function flatten (oldArr) {
var newArr = []
for(var i = 0; i < oldArr.length; i++){
if(Array.isArray(oldArr[i])){
newArr = newArr.concat(flatten(oldArr[i]))
} else {
newArr.push(oldArr[i])
}
}
return newArr;
}
flatten([1,[2,[3,4]],5])
复制代码
参考4
function nestedEvenSum(obj, sum=0) {
for (var key in obj) {
if (typeof obj[key] === 'object'){
sum += nestedEvenSum(obj[key]);
} else if (typeof obj[key] === 'number' && obj[key] % 2 === 0){
sum += obj[key];
}
}
return sum;
}
nestedEvenSum({c: 4,d: {a: 2, b:3}})
复制代码
参考5
function collectStrings(obj) {
let newArr = []
for (let key in obj) {
if (typeof obj[key] === 'string') {
newArr.push(obj[key])
} else if(typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
newArr = newArr.concat(collectStrings(obj[key]))
}
}
return newArr
}
var obj = {
a: '1',
b: {
c: 2,
d: 'dd'
}
}
collectStrings(obj)
复制代码
5. 总结
递归精髓是,往往要先想好常规部分是怎样的,在考虑递归部分,下面是 JavaScript 递归常用到的方法
- 数组:
slice,concat - 字符串:
slice,substr,substring - 对象:
Object.assign
以上所述就是小编给大家介绍的《用 JavaScript 的方式理解递归》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 深入理解几种单例模式的实现方式
- 不理解 Java Steam?一步步梳理其工作方式
- 【JS系列】一起理解对象的7种创建方式(全)
- ICML 最佳论文提名论文:理解词嵌入类比行为新方式
- Google Brain新成果:一个能够理解机器思维方式的AI翻译器
- 用自己的方式(图)理解constructor、prototype、__proto__和原型链
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ajax基础教程
(美)阿斯利森、(美)舒塔、金灵 / 金灵 / 人民邮电出版社 / 2006-02-01 / 35.00元
Ajax技术可以提供高度交互的Web应用,给予用户更丰富的页面浏览体验。本书重点介绍Ajax及相关的工具和技术,主要内容包括XMLHttpRequest对象及其属性和方法、发送请求和处理响应、构建完备的Ajax开发工具、使用JsUnit测试JavaScript、分析JavaScript调试工具和技术,以及Ajax开发模式和框架等。本书中所有例子的代码都可以从Apress网站本书主页的源代码(Sou......一起来看看 《Ajax基础教程》 这本书的介绍吧!