最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

function generator javascript - Stack Overflow

programmeradmin2浏览0评论

I need to make a function generator that iterates over an infinite sequence, like the fibonacci sequence. It should return the next value in the sequence when called. I am given a function prototype:

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

it should be used like this:

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

I am confused about what is executing every time I call fib(). I tried to do something like

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;
    }
  }
}

But it's not working. I don't know how to set it up to run the if/else for the first two numbers in the fib sequence and then run the while loop once for each subsequent call.

I need to make a function generator that iterates over an infinite sequence, like the fibonacci sequence. It should return the next value in the sequence when called. I am given a function prototype:

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

it should be used like this:

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

I am confused about what is executing every time I call fib(). I tried to do something like

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;
    }
  }
}

But it's not working. I don't know how to set it up to run the if/else for the first two numbers in the fib sequence and then run the while loop once for each subsequent call.

Share Improve this question edited Oct 30, 2014 at 4:36 Weafs.py 23k9 gold badges57 silver badges79 bronze badges asked Oct 30, 2014 at 4:32 user137717user137717 2,1854 gold badges28 silver badges51 bronze badges 6
  • 2 Do you know what yield does? – ncksllvn Commented Oct 30, 2014 at 4:40
  • i think it's kind of like a return that only pauses a function instead of terminating it after returning a value – user137717 Commented Oct 30, 2014 at 4:42
  • 2 If this is an assignment/homework (from "I am given a function prototype"), then it looks like you are supposed to learn about closures. Not write generators with yield. – Bergi Commented Oct 30, 2014 at 5:14
  • If our answers have been helpful to you, please mark one one of the answers as correct. – ncksllvn Commented Oct 30, 2014 at 15:22
  • 1 @user137717: Much the same :) But yes, that method stub is a definitive hint at using a closure. – Bergi Commented Oct 30, 2014 at 18:28
 |  Show 1 more ment

4 Answers 4

Reset to default 7

If you want to use ES6 generators and yield, then here's the approach:

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

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

One way to iterate over the results is with a for-of loop:

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

Note that the destructuring assignment var [prev, current] = is supported in FF and Traceur but not in Chrome or node at present. If necessary rewrite it as:

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

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

If you want the semantics of the function prototype you were given, then:

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

If you ask me, yield has no place in this function, just some clever use of JavaScript closure.

You had the right idea in the beginning - you do need a function that returns a function. Outside of the inner function have a couple variables - one for the old, one for the next. Inside the function, all you have to do is calculate the new next value, and then set old to the next's previous value. To switch their values, you'll need a placeholder variable.

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()

Of course, this doesn't account for the the first function call, which is a special case (1 should be returned twice.) But I'll leave that to you to figure out :-)

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

For a high level overview on how to use generators, checkout this post.

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
发布评论

评论列表(0)

  1. 暂无评论