In my current project I have objects of the following structure:CanvasBundle - ObjectSome elements...gridCanvasaxesCanvasfunctions[] (contains unknown number of functionCanvases)overlayCanvasI'd like to write an iterator which would iterative over all the canvases (grid/axes/func/func1/func2/.../overlay).I've currently implemented it like this:function makeCanvasBundleIterator(canvasBundle) {  var nextIndex = 0;  var functionIndex = 0;  return {    next: function() {      var value;      switch (nextIndex) {      case 0:        value = canvasBundle.grid;        break;      case 1:        value = canvasBundle.axes;        break;      case 2:        value = canvasBundle.functions[functionIndex];        break;      case 3:        value = canvasBundle.overlay;        break;      default:        break;      }      if (nextIndex != 2 || functionIndex == canvasBundle.functions.length -1) {         nextIndex++;       } else {         functionIndex++       }      return nextIndex <= 4 ?         {value: value, done: false} :        {done: true};    }  };}This allows me to do the following: var it = makeCanvasBundleIterator(canvasBundle);var next;while (!(next = it.next()).done) {  console.log(next.value);}Coming from C, this code does not look clean at all. Since I'm a real JS beginner, I'd like a review with suggestions/advice how I can clean it up. Maybe there even is a completely different/better approach.
JavaScript Iteration
javascript;iterator;iteration
If you're implementing the iteration protocol - use a generator: function* makeCanvasBundleIterator(canvasBundle) { // note the *   yield canvasBundle.grid;   yield canvasBundle.axes;   yield* canvasBundle.functions; // note the * for inner yield   yield canvasBundle.overlay;}And that's your entire function. Generators give us a declarative way to deal with the iteration protocol. Now, you can also consume the result better - this is regardless if you want to use the generator or your own solution:for(const value of makeCanvasBundleIterator(...)) {    // access value here}If you'd like to take a more OOP approach and signal that a CanvasBundle is an iterable, you can implement the iterable protocol with Symbol.iterator :CanvasBundle.prototype[Symbol.iterator] = function*() {   yield canvasBundle.grid;   yield canvasBundle.axes;   yield* canvasBundle.functions; // note the * for inner yield   yield canvasBundle.overlay;}Which would allow you to iterate the canvas bundle itself:for(const item of canvasBundle) {    // iterate item}Array.from(canvasBundle); // get iteration result as array[...canvasBundle]; // also works and converts to an array. And use it anywhere you'd use a regular iterator. 