javascript – 为什么递归生成器函数在ES2015中不起作用?

我试图了解ES2015中的生成器,并创建了一个递归因子函数.但它不行.我已经提到已经存在的问题,如 this这个话题,但这没有帮助.
function* fact (n) {
   if (n < 2) {
     yield 1;
   } else {
     yield* (n * fact(n-1));
   }
}

let b = fact(5);
console.log(b.next());

任何人都会发现我在这里遗失的明显问题吗?我在JSfiddle中使用了JavaScript-1.7 here

解决方法

Can anyone find any obvIoUs issues I am missing here?

事实返回一个迭代器,但是你试图用一个数字来重复它:n * fact(n-1).那不行!

因为事实返回一个迭代器,但是你也希望将迭代器的最后一个值乘以n(即它不是尾递归),所以你也不能简单地生成它.
您需要从内部调用中显式迭代结果,重新引用该值并记住最后一个值,以便可以使用多个值:

function* fact (n) {
   if (n < 2) {
     yield 1;
   } else {
     let last;
     for(last of fact(n-1)) {
       yield last;
     }
     yield n * last;
   }
}

Array.from(fact(5)); // [1,2,6,24,120]

如果您将函数更改为尾递归,则会稍微缩短(并且更好),但结果也会不同(因为我们以不同的顺序执行操作,至少在此实现中):

function* fact (n,acc=1) {
   yield acc
   if (n > 1) {
     yield* fact(n-1,acc * n);
   }
}
Array.from(fact(5)); // [1,5,20,60,120]

我个人只会写一个非递归版本:

function* fact (n) {
  let result = 1;
  let i = 0;
  while (i < n) {
    yield result = result * ++i;
  }
}
Array.from(fact(5)); // [1,120]

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...