mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 18:32:22 +00:00
edit function/tail call
This commit is contained in:
parent
19652900c9
commit
aba2df6647
@ -237,15 +237,15 @@ rest参数中的变量代表一个数组,所以数组特有的方法都可以
|
||||
|
||||
```javascript
|
||||
|
||||
function push(array, ...items) {
|
||||
function push(array, ...items) {
|
||||
items.forEach(function(item) {
|
||||
array.push(item);
|
||||
console.log(item);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var a = [];
|
||||
push(a, 1, 2, 3)
|
||||
push(a, 1, 2, 3)
|
||||
|
||||
```
|
||||
|
||||
@ -703,9 +703,9 @@ function f(x) {
|
||||
|
||||
尾调用之所以与其他调用不同,就在于它的特殊的调用位置。
|
||||
|
||||
我们知道,函数调用会在内存形成一个“调用栈”(call stack),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,就会在A的调用栈上方,再形成一个B的调用栈。等到B运行结束,将结果返回到A,B的调用栈才会消失。如果函数B内部还调用函数C,那就还有一个C的调用栈,以此类推。
|
||||
我们知道,函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用记录上方,还会形成一个B的调用记录。等到B运行结束,将结果返回到A,B的调用记录才会消失。如果函数B内部还调用函数C,那就还有一个C的调用记录栈,以此类推。所有的调用记录,就形成一个“调用栈”(call stack)。
|
||||
|
||||
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用栈,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用栈,取代外层函数的调用栈就可以了。
|
||||
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用记录,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就可以了。
|
||||
|
||||
```javascript
|
||||
function f(x) {
|
||||
@ -723,15 +723,15 @@ function f(x) {
|
||||
g(3);
|
||||
```
|
||||
|
||||
上面代码中,如果函数g不是尾调用,函数f就需要保存内部变量m和n的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除 f(x) 的调用栈,只保留 g(3) 的调用栈。
|
||||
上面代码中,如果函数g不是尾调用,函数f就需要保存内部变量m和n的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除 f(x) 的调用记录,只保留 g(3) 的调用记录。
|
||||
|
||||
这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用栈。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用栈只有一项,这将大大节省内存。这就是“尾调用优化”的意义。
|
||||
这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用记录。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。这就是“尾调用优化”的意义。
|
||||
|
||||
### 尾递归
|
||||
|
||||
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
|
||||
|
||||
递归非常耗费内存,因为需要同时保存成千上百个调用栈,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用栈,所以永远不会发生“栈溢出”错误。
|
||||
递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生“栈溢出”错误。
|
||||
|
||||
```javascript
|
||||
function factorial(n) {
|
||||
@ -742,9 +742,9 @@ function factorial(n) {
|
||||
factorial(5) // 120
|
||||
```
|
||||
|
||||
上面代码是一个阶乘函数,计算n的阶乘,最多需要保存n个调用栈,复杂度 O(n) 。
|
||||
上面代码是一个阶乘函数,计算n的阶乘,最多需要保存n个调用记录,复杂度 O(n) 。
|
||||
|
||||
如果改写成尾递归,只保留一个调用栈,复杂度 O(1) 。
|
||||
如果改写成尾递归,只保留一个调用记录,复杂度 O(1) 。
|
||||
|
||||
```javascript
|
||||
function factorial(n, total) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user