ES6中的尾递归优化

栏目: JavaScript · 发布时间: 5年前

内容简介:递归是我们经常会用到的,然而没有限制的递归,往往会引起爆栈的问题,于是尾递归的优势便体现了出来。假如我们需要实现1+2+3+4+….+n的一个小程序,用递归实现的话,如下:递归正常值是没有问题的,

递归是我们经常会用到的,然而没有限制的递归,往往会引起爆栈的问题,于是尾递归的优势便体现了出来。

递归

假如我们需要实现1+2+3+4+….+n的一个小程序,用递归实现的话,如下:

function sum(x) {
    if (x === 1) {
        return 1;
    }
    return x + sum(--x);
}

递归正常值是没有问题的,

console.log( sum(10) );       // 55
console.log( sum(55555) );    // Uncaught RangeError: Maximum call stack size exceeded

当递归层数到达一定值后,就会出现爆栈了,当然不同浏览器的最大递归层数是不一样的。

尾递归

函数调用自身的过程,称为递归,如果最后调用的是自身,就称为尾递归。在ES6中,有了尾递归优化这个概念。我们将刚才的递归改写成尾递归:

function sum1(x, total) {
    if (x === 1) {
        return x + total;
    }
    return sum1(x - 1, x + total);
}

在普通递归时,最后return了x + sum(–x),即每次调用下一个sum函数时,都需要保存当前作用域下的其他变量(比如x),所以很容易出现栈溢出的问题。

而尾递归中,由于最后返回的是函数,往往不需要保留先前的东西,仅仅记录下一次调用的函数即可,所以可以节省大量的内存。

在chrome下尝试:

console.log( sum1(10, 0) ); // 55
console.log( sum1(55555, 0) ); // Uncaught RangeError: Maximum call stack size exceeded

依旧是爆栈了。

查阅了资料发现,v8中尾递归优化是默认关闭的,尝试了以下方法均以 失败 告终:

  1. 严格模式下运行(chrome74.0.3729.157 64位版本)。
  2. chrome下开启Experimental JavaScript(版本同上)。
  3. node环境下(v8.11.1)。
  4. mac safari浏览器(12.0.3版本)。

至于为何没有默认开启呢?可以查看下这篇文章: 尾递归的后续探究

其他方式

如果想实现递归但又怕爆栈这种情况呢?我们可以使用while循环。

function sum2(n) {
    var sum = 0;
    while (n > 0) {
        sum += n;
        n--;
    }
    return sum;
}

console.log( sum2(10) ); // 55
console.log( sum2(55555, 0) ); // 1543206790

以循环的方式也是可以完成的。

整个demo地址: github


以上所述就是小编给大家介绍的《ES6中的尾递归优化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

传统企业,互联网在踢门

传统企业,互联网在踢门

刘润 / 中国华侨出版社 / 2014-7 / 42

1、第一本传统企业互联网化的战略指导书,首次提出“互联网加减法”,迄今最清晰的转型公式 鉴于目前很多传统企业“老办法不管用,新办法不会用”的现状,本书将用“互联网的加减法” 这个简单模型清晰地说明商业新时代的游戏规则和全新玩法,帮助传统企业化解“本领恐慌” 。 2、小米董事长&CEO 金山软件董事长雷军,新东方教育科技集团董事长兼CEO俞敏洪,复旦大学管理学院院长陆雄文,复旦大学博士、......一起来看看 《传统企业,互联网在踢门》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具