Creating An Iterator Function By Scratch in JavaScript

Picture shows Jason A. Martin - Software Engineer, Indie Game Developer, Tech Evangelist, Entrepreneur.

In this JavaScript code snippet, I show how to create a custom iterator function. Generally, you're probably going to use a generator function when you want to step through a data stream, but today I'm going to jot down a little code note about creating a custom iterator in JavaScript easily, thanks to closure.

There are many reasons to use a generator, but my specific case is thinking about iterating through a collection of article files so that I can pull them out one at a time as needed in more readable fashion.


Let's first look at a simple generator function (this is an ES6 feature).

function* coolGenerator() {
  yield 1;
  yield 2;
  yield 3;

coolGenerator(); // output: { value: 1, finished: false }
coolGenerator(); // output: { value: 2, finished: false }
coolGenerator(); // output: { value: 3, finished: false }
coolGenerator(); // output: { value: undefined, finished: true }

Each time you call the generator function, it resumes where it left off and executes until the next yield. After the final yield, it just returns undefined with a finished state of true.


We're going to create a simple iterator by passing in an array, returning out a function with a next() property and using closure to keep track of state. Additionally, we'll modify it to pass the finished object value as a generator does (except ours will pass out finished: true on the last call in the array).

const articles = ['', '', '', ''];

function getData(array){
  let i =0;
  const nextYield = {
    next: function() {
            const element = array[i];
            return { value: element, finished: (i >= array.length) };
  return nextYield;

Now that we have it setup, we're ready to call it. I also want to have two streams going (for whatever reason).

const allArticles = getData(articles);
const processArticlesAgain = getData(articles);; // { value: '', finished: false }; // { value: '', finished: false }; // { value: '', finished: false }; // { value: '', finished: true }; // { value: '', finished: false }

As you can see, we did four calls to and got our four articles along with a finished: true on the last call.

Additionally we called and got another stream going.