DEV Community

loading...

Javascript Generator Function Basics

Muhammad Yusuf
・3 min read

We'll learn about javasciprt feature not many people use or talk about. It's generator function. So what is it?

Generator function is a function that can generate more than one value. So how do we make it?

function* greet() {
  yield 'Hello World!'
}
Enter fullscreen mode Exit fullscreen mode

So what's different with regular function? First, instead of function we define it with asterisk function* to indicate this isn't your regular function. Then instead of return a value, we yield it. The special thing about yield is that the function can be yield-ed more than once!

function* greet() {
  yield 'Hello world!'
  yield 'Hello again!'
  yield 'Hello, I am bored'
}
Enter fullscreen mode Exit fullscreen mode

Now how do we get those values? First we can turn it into generator object by invoking it.

let word = greet()
console.log(word) // Object [Generator] {}
Enter fullscreen mode Exit fullscreen mode

And then we can get the values by invoking the next method from the word variable.

let word = greet()
console.log(word.next()) // { value: 'Hello world!', done: false }
Enter fullscreen mode Exit fullscreen mode

Notice that the value logged turned into an object with 'Hello world!' there in value property. And we have another property called done with value false, what is that? The done property indicates whether all the value from greet function has been yielded or not. In a simple way, it tells you:

Hey this is the value you wanted, but I'm not done yet. I still have more.

So if we want to get the other values, we can do it again and again, you get the idea:

let word = greet()
console.log(word.next()) // { value: 'Hello world!', done: false }
console.log(word.next()) // { value: 'Hello again!', done: false }
console.log(word.next()) // { value: 'Hello, I am bored!', done: false }
Enter fullscreen mode Exit fullscreen mode

But wait, is that it? Kind of. Because you can still call next after that. It's just... not too necessary. But hey it's your code.

...
console.log(word.next()) // { value: 'Hello, I am bored!', done: false }
console.log(word.next()) // { value: undefined, done: true }
console.log(word.next()) // { value: undefined, done: true }
console.log(word.next()) // { value: undefined, done: true }
Enter fullscreen mode Exit fullscreen mode

Working with loop

Now assuming the generator function is not ours (maybe it's a package) how do we know how may values can we yield? We can get all of them by using for ... of loop.

for(let w of word) {
  console.log(w)
}
/*
Hello world!
Hello again!
Hello, I am bored
*/
Enter fullscreen mode Exit fullscreen mode

Endless value generator

Now say that we want to get the first 5 numbers that are divisible by 3 (3, 6, 9, 12, 15). But when i want the first 7 numbers, 18 and 21 will come along. We can make our function like this:

function* divisibles3() {
  let num = 1
  while(true) {
    if(num % 3 === 0) yield num
    num++
  }
}

let n = divisibles3()
Enter fullscreen mode Exit fullscreen mode

We can get the values by calling it as many as we want:

// 1. First 5
console.log(n.next().value) // 3
console.log(n.next().value) // 6
console.log(n.next().value) // 9
console.log(n.next().value) // 12
console.log(n.next().value) // 15

// 2. Fisrt 7
for(let i = 0; i < 5; i++) {
  console.log(n.next().value) // 3, 6, 9, 12, 15, 18, 21
}
Enter fullscreen mode Exit fullscreen mode

Or better, we can make it dynamic so the function can take any divisible:

function* divisibles(div) {
  let num = 1
  while(true) {
    if(num % div === 0) yield num
    num++
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we can get any first numbers divisible by any number:

// 1. First 3 divisible by 4
let n = divisibles(4)
for(let i = 0; i < 3; i++) {
  console.log(n.next().value) // 4, 8, 12
}
// 2. Fisrt 4 divisible by 7
let n = divisibles(7)
for(let i = 0; i < 4; i++) {
  console.log(n.next().value) // 7, 14, 21, 28
}
Enter fullscreen mode Exit fullscreen mode

Source:

dcode: https://www.youtube.com/watch?v=EzdgkEMvrvA&t=4s

Discussion (0)