这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战
学习贵在坚持, 笔记是灵魂, 温故而知新, 时不时翻一翻, 回顾一下知识点, 加深记忆, 事半功倍!
前文我们学习了关于 JavaScript 中的 日期时间处理库 & Date 对象`
今天来学习 基于对象编程的JavaScript 函数-递归
1. JavaScript 函数-递归
函数在 JavaScript 中的地位毋庸置疑, 可以说函数就是 JavaScript 编程的基础.
我们使用 function 关键字开头的表达式创建一个功能函数,
另外 ES6 中的 箭头函数: () => { 函数体 } 也是函数的一种表示方法.
2. 递归函数
在工作中经常需要处理数据, 比如涉及到算法, 与树结构相关的数据结构的算法, 使用 递归 就可以很简洁地实现. 这时候就有用到递归了.
2.1 定义:
函数自己调用自己, 即 调用自身的函数 我们称之为 递归函数.
2.2 递归需要注意的问题
当然由于是自身调用自己, 这时候就要考虑到会不会无限循环, 而带来的内存消耗的问题了. 一般需要有终止调用的判断: 防止调用太多次而出现栈溢出的情况.
比如函数自己调用自己达到成千上万次, 这时候就要考虑到很可能会导致的错误: "最大调用栈溢出"(Maximum call-stack size exceeded).
2.3 示例
接下来我们用 求一个数的 N 次方(幂) 举例来说,下面这种求 幂运算 的函数实现:
/**
* 求 幂运算 函数
* @param {baseNumber} 底(基)数
* @param {exponent} 幂次数
* @returns
*/
function exponentiation (baseNumber, exponent) {
if(exponent == 0) {
return 1;
} else {
return baseNumber * exponentiation(baseNumber, exponent - 1);
}
console.log(exponentiation(2,3));// --> 8
这种实现方式 可以说比其使用循环实现的版本更清楚地描述了这个概念。此函数使用更小的指数多次调用自身以实现重复乘法。
2.4 递归与循环 的效率问题
上面这个实现也有一个问题: 就是在经典的 JavaScript 实现中,它的速度大约是循环版本的三分之一。而且通过简单循环运行通常比多次调用函数成本低。
速度与易读性的困境是一个经典的问题。你可以将其视为对人类友好和对机器友好之间的一种对立与统一。几乎任何程序都可以通过使其更大、更复杂来加快运行速度。程序员必须做出适当的权衡。
在有些函数中,使用循环版本仍然相当简单且易于阅读。用递归版本替换它反而没有多大意义。但是,通常程序处理这样复杂的概念时,放弃一些效率以使程序更直截了当是有帮助的。
担心效率可能会分散注意力。因此,我们总是先写一些正确且易于理解的东西。因为大多数代码根本不会经常执行,所以它们不足以花费任何大量的时间而担心它太慢,你可以在后面进行测量并在必要时进行改进
2.5 递归也有高效的高光时刻
然而递归并不总是一种替代循环的低效方法。使用递归比使用循环更容易解决一些问题. 大多数情况下,这些问题需要探索或处理几个“分支”,而每个分支可能会再次扩展到更多分支。
看一下如下这个难题: 使用递归实现以下?
当从数字 1 开始,重复加 5 或乘以 3,可以生成一个由无数的数字组成的集合。对于给定一个数字,要找到产生这个数字的一系列这样的加法和乘法,该如何编写函数呢?
例如,可以通过首先乘以 3 然后再两次加上 5 来达到数字 13,而数字 15 根本不可能达到。
更多阅读
更多更文阅读请查收:
【JS】日期处理库 & Date 对象、 【JS】基于对象编程的 JavaScript-字符串对象、 【JS】布尔(boolean)类型
【数据结构】数据结构-对象和数组(二)数组 Array、 【数据结构】数据结构-对象和数组(一)对象 Object、 【数据结构】深入了解 JSON
【Node.js】文件系统模块、 【Node.js】HTTP 模块
【Node.js】安装&文档、 【工具准备】、 【开工】、 【详细步骤(四)】、 【模块处理工具(五)】、 【模块化编程的理解】
跟上节奏, 一步一步向全栈进击!
接下来会继续详细学习 JavaScript 的其他相关方法, 冲鸭!! xdm
学习用到的效率工具, 提高开发效率, 为我们的开发提效赋能!
跟上前进的步伐, 向前加油吧
加油!! go~~