美文网首页
ES6之函数扩展

ES6之函数扩展

作者: 付出的前端路 | 来源:发表于2018-07-31 15:31 被阅读0次

目录
一、 函数参数的默认值
二、rest参数
三、严格模式
四、name 属性
五、箭头函数
六、双冒号运算符(目前报错,只是提案。)
七、重点: 尾调用优化,尾递归优化( Fibonacci 数列)
八、函数参数尾逗号

尾递归
总结一下,递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。对于其他支持“尾调用优化”的语言(比如 Lua,ES6),只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。

下面是一个正常的递归函数。

function sum(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1);
  } else {
    return x;
  }
}

sum(1, 100000)
// Uncaught RangeError: Maximum call stack size exceeded(…)

上面代码中,sum是一个递归函数,参数x是需要累加的值,参数y控制递归次数。一旦指定sum递归 100000 次,就会报错,提示超出调用栈的最大次数。

蹦床函数(trampoline)可以将递归执行转为循环执行。

function trampoline(f) {
  while (f && f instanceof Function) {
    f = f();
  }
  return f;
}

上面就是蹦床函数的一个实现,它接受一个函数f作为参数。只要f执行后返回一个函数,就继续执行。注意,这里是返回一个函数,然后执行该函数,而不是函数里面调用函数,这样就避免了递归执行,从而就消除了调用栈过大的问题。

然后,要做的就是将原来的递归函数,改写为每一步返回另一个函数。

function sum(x, y) {
  if (y > 0) {
    return sum.bind(null, x + 1, y - 1);
  } else {
    return x;
  }
}

上面代码中,sum函数的每次执行,都会返回自身的另一个版本。

现在,使用蹦床函数执行sum,就不会发生调用栈溢出。

trampoline(sum(1, 100000))
// 100001

蹦床函数并不是真正的尾递归优化,下面的实现才是。

function tco(f) {
  var value;
  var active = false;
  var accumulated = [];

  return function accumulator() {
    accumulated.push(arguments);
    if (!active) {
      active = true;
      while (accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}

var sum = tco(function(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1)
  }
  else {
    return x
  }
});

sum(1, 100000)
// 100001

上面代码中,tco函数是尾递归优化的实现,它的奥妙就在于状态变量active。默认情况下,这个变量是不激活的。一旦进入尾递归优化的过程,这个变量就激活了。然后,每一轮递归sum返回的都是undefined,所以就避免了递归执行;而accumulated数组存放每一轮sum执行的参数,总是有值的,这就保证了accumulator函数内部的while循环总是会执行。这样就很巧妙地将“递归”改成了“循环”,而后一轮的参数会取代前一轮的参数,保证了调用栈只有一层。

相关文章

  • es6的数值,函数,字符串扩展

    一、es6的数值扩展 二、es6的函数扩展 代码效果:对象解构在函数中的应用 三、es6字符串扩展 常用方法 代码...

  • ES6之函数扩展

    目录一、 函数参数的默认值二、rest参数三、严格模式四、name 属性五、箭头函数六、双冒号运算符(目前报错,只...

  • ES6之函数扩展

    (1)rest参数 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用argument...

  • ES6之函数扩展

    关键词:函数扩展 参数的默认值 属性的默认值 rest:获取函数的多余参数 箭头函数 箭头函数使用注意:1.函数体...

  • es6之扩展运算符 三个点(...)

    es6之扩展运算符 三个点(...)对象的扩展运算符数组的扩展运算符总结es6之扩展运算符 三个点(…)对象的扩展...

  • ES6基础笔记二

    ES6 箭头函数、函数扩展 ES5: function add(a,b){return a+b;}console....

  • ES6扩展归纳

    ES6扩展归纳 介绍ES6相比与ES5在原有对象上的扩展,包括字符串、正则、数值、函数、数组、对象等扩展,本文是阮...

  • ES6&函数扩展

    ES6函数的扩展 1.函数默认值 定义:ES6允许为函数设定默认值,即直接写在参数定义的后面 示例function...

  • es6的this的指向性问题详解(接着上一篇文章)

    我们都知道在es6中函数的扩展多了箭头函数,那么箭头函数中的this如何指向呢? 下面我们来看一看: 其实es6的...

  • ES6函数扩展

    function扩展 ES6在原有ES5基础上对function的扩展 1.默认值 ES6 允许为函数的参数设置默...

网友评论

      本文标题:ES6之函数扩展

      本文链接:https://www.haomeiwen.com/subject/ihchvftx.html