递归
是指在函数的定义中使用函数自身的方法。程序调用自身的编程技巧称为递归
递归函数
在函数定义中调用自身(自己调用自己)
_
function fn() {
if (结束条件) { // 不加结束条件 小心死循环。。。
return
}
fn() // 调用自己
}
fn()
注意:递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。
递归递增
n从0依次递增为10
var n = 0
function fe() {
if (n >= 10) {
return
}
n++
console.log(n)
fe()
}
fe()
从1累加到5
// 求1 ~ 5 所有数的和 (从1到5 1 + 2 + 3 + 4 + 5)
function sum(n) {
if (n <= 1) {
return 1
}
return n + sum(n - 1)
}
// sum(3) 1 + 2 + 3
// R 3 + sum(3 - 1) => 3 + sum(2)
// R 3 + 2 + sum(2 - 1) => 3 + 2 + sum(1)
// R 3 + 2 + 1
// 6
递归求和
求1 ~ 100 所有数的和
// 1 ~ 10 求和
function add(n) {
if (n <= 1) {
return 1
}
return n + add(n - 1)
}
var result = add(10)
console.log(result) // 55
// add(10) => 10 + add(10 - 1)
// => 10 + 9 + add(9 - 1)
// => 10 + 9 + 8 + add(8 - 1)
// => 10 + 9 + 8 + 7 + add(7 - 1)
// => 10 + 9 + 8 + 7 + 6 + add(6 - 1)
// => 10 + 9 + 8 + 7 + 6 + 5 + add(5 - 1)
// => 10 + 9 + 8 + 7 + 6 + 5 + 4 + add(4 - 1)
// => 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + add(3 - 1)
// => 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + add(2 - 1)
// => 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1
// 55
求 1 ~ 100 能够被2整除的数 的和
var total = 0
for (var i = 1; i <= 100; i++) {
if (i % 2 === 0) {
total += i
}
}
console.log(total) // 2550
递归方式
function sum(n) {
if (n < 1) {
return 0
}
if (n % 2 === 0) {
return n + sum(n - 1)
}
return sum(n - 1)
}
console.log(sum(100)) // 2550
// sum(100) => n + sum(n - 1)
// R 100 + sum(100 - 1) sum(99)
// R 100 + sum(99 - 1) sum(98)
// R 100 + 98 + sum(98 - 1) sum(97)
// R 100 + 98 + sum(97 - 1) sum(96)
// R 100 + 98 + 96 + sum(96 - 1) sum(95)
// R 100 + 98 + 96 + sum(95 - 1) sum(94)
// R 100 + 98 + 96 + 94 + sum(94 - 1) sum(93)
// ......
求 1 ~ 100 能够被3整除的数 的和
var total = 0
for (var i = 1; i <= 100; i++) {
if (i % 3 === 0) {
total += i
}
}
console.log(total) // 1683
递归方式
function sum(n) {
if (n < 1) {
return 0
}
if (n % 3 === 0) {
return n + sum(n - 1)
}
return sum(n - 1)
}
console.log(sum(100)) // 1683
求 1 ~ 100 能够被3和5整除的数 的和
var total = 0
for (var i = 1; i <= 100; i++) {
if ((i % 3 === 0) && (i % 5 === 0)) {
total += i
}
}
console.log(total) // 315
递归方式
function sum(n) {
if (n < 1) {
return 0
}
if (n % 15 === 0) {
return n + sum(n - 1)
}
return sum(n - 1)
}
console.log(sum(100))
阶乘
function factorial(n) {
if (n == 1) return n;
return n * factorial(n - 1)
}
console.log(factorial(5)) // 5 * 4 * 3 * 2 * 1 = 120
尾递归(阶乘优化)
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。 递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生"栈溢出"错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误。
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1);
}
factorial(5) // 120
// 尾递归
function factorial(n, total) {
if (n === 1) return total;
return factorial(n - 1, n * total);
}
factorial(5, 1) // 120
查找上一个哥哥元素节点
<body>
<ul id="list">
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
<li>item9</li>
<li>item10</li>
</ul>
<script>
const list = document.getElementById('list')
// while循环
function findPrev1(node) {
let p = node.previousSibling
while(p && p.nodeType !== 1) {
p = p.previousSibling
}
return p
}
console.log(findPrev1(list.children[2]))
// 递归方式
function findPrev2(node) {
const p = node.previousSibling
if (p && p.nodeType === 1) {
return p
}
return findPrev2(p)
}
console.log(findPrev2(list.children[2]))
</script>
</body>
koa-compose源码
function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
return Promise.reject(err)
}
}
}
}
----------------------------------------------------------------------------------------------------------------
参考文章&&强烈推荐:布罗利