函数发生器javascript

时间:2014-10-30 04:32:48

标签: javascript generator

我需要创建一个迭代无限序列的函数生成器,比如fibonacci序列。它应该在调用时返回序列中的下一个值。我得到了一个函数原型:

function genfib() {
  return function fib() {
  }
}

它应该像这样使用:

var fib = genfib();
fib(); // -> returns 0
fib(); // -> returns 1
fib(); // -> returns 1
fib(); // -> returns 2

每次拨打fib()时,我都对执行的内容感到困惑。我试着做一些像

这样的事情
function genfib() {
  var count = 1;
  if (count === 1) {
    count++;
    yield 0;
  }
  else if (count === 2) {
    count++;
    yield 1;
  }
  var a = 0;
  var b = 1;
  return function fib() {
    while(1) {
      count = a + b;
      a = b;
      b = count;
      yield count;
    }
  }
}

但它不起作用。我不知道如何设置它来为if/else序列中的前两个数字运行fib,然后为每个后续调用运行一次while循环。

4 个答案:

答案 0 :(得分:7)

如果您想使用ES6生成器和yield,那么这就是方法:

function *fibonacci() {
    var [prev, current] = [0, 1];

    while (true) {
        [prev, current] = [current, current+prev];
        yield current;
    }
}

迭代结果的一种方法是使用for-of循环:

for (var v of fibonacci()) {
    console.log(v);
    if (v > 100) break;
}

请注意,FF和Traceur支持解构分配var [prev, current] =,但目前不支持Chrome或节点。如有必要,请将其重写为:

function *fibonacci() {
    var prev = 0, current = 1, oldprev;

    while (true) {
        oldprev = prev;
        prev = current;
        yield current += oldprev;
    }
}

如果你想要给出函数原型的语义,那么:

function genfib() {
    var iterator = fibonacci();
    return function fib() {
        return iterator.next().value;
    };
}

答案 1 :(得分:2)

如果您问我,yield在此功能中没有任何地方,只需巧妙地使用JavaScript closure

你在开始时有正确的想法 - 你需要一个返回一个函数的函数。内部函数之外有几个变量 - 一个用于旧的,一个用于下一个。在函数内部,您所要做的就是计算新的next值,然后将old设置为next之前的值。要切换它们的值,您需要一个占位符变量。



function genfib() {
  var next = 1
  var old = 0
  return function fib() {
    var newNext= next + old
    old = next
    next = newNext
    return next
  }
}

var fib = genfib()

var result = []

for ( var i = 0; i < 10; i++ )
  result.push( fib() )

document.body.innerHTML = result.join()
&#13;
&#13;
&#13;

当然,这并不能解释第一个函数调用,这是一个特殊情况(1应该返回两次。)但是我会留给你弄清楚: - )< / p>

答案 2 :(得分:1)

function* fib(num) {
  var a = num, b = a + 1, c = a;

  while (true) {
    yield a;
    c = a;
    a = b;
    b = c + b;
  }
}

var it = fib(0);
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().value); // 3
console.log(it.next().value); // 5
console.log(it.next().value); // 8
console.log(it.next().value); // 13

有关如何使用生成器的高级概述,checkout this post

答案 3 :(得分:0)

function* fibonacci(){
  var fn1 = 1;
  var fn2 = 1;
  while (true){  
    var current = fn2;
    fn2 = fn1;
    fn1 = fn1 + current;
    var reset = yield current;
    if (reset){
        fn1 = 1;
        fn2 = 1;
    }
  }
}

var sequence = fibonacci();
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
console.log(sequence.next().value);     // 3
console.log(sequence.next().value);     // 5
console.log(sequence.next().value);     // 8
console.log(sequence.next().value);     // 13
console.log(sequence.next(true).value); // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
console.log(sequence.next().value);     // 3