Skip to content

Instantly share code, notes, and snippets.

@juanmaguitar
Last active September 28, 2016 15:37
Show Gist options
  • Save juanmaguitar/9ab2755379432f7c468778842c675817 to your computer and use it in GitHub Desktop.
Save juanmaguitar/9ab2755379432f7c468778842c675817 to your computer and use it in GitHub Desktop.
Iterators ES-2015

Iterators (ES-2015)

Iterators

An object is an iterator when it knows how to access items from a collection one at a time, while keeping track of its current position within that sequence.

In JavaScript an iterator is an object that provides a next() method which returns the next item in the sequence. This method returns an object with two properties: done and `value.

function makeIterator(array){
    var nextIndex = 0;
    
    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    }
}

var it = makeIterator(['yo', 'ya']);

console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done);  // true

Iterables

An object is iterable if it defines its iteration behavior, such as what values are looped over in a for..of construct. Some built-in types, such as Array or Map, have a default iteration behavior, while other types (such as Object) do not.

In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a Symbol.iterator key

### Built-in iterables

String, Array, TypedArray, Map and Set are all built-in iterables, because the prototype objects of them all have a Symbol.iterator method.

### Syntaxes expecting iterables

Some statements and expressions are expecting iterables, for example the for-of loops, spread operator, yield*, and destructuring assignment.

> function logIterator( iterator ) {
    var current;
    while( true ) {
        current = iterator.next();
        if ( current.done ) {
            break;
        }
        console.log( current.value );
    }
}

>logIterator( ["a","b", "c", "d"].entries() );
[0, "a"]
[1, "b"]
[2, "c"]
[3, "d"]

> logIterator( ["a","b", "c", "d"].keys() );
0
1
2
3

> var map = new Map();
> map.set(0, "a");
> map.set(1, "b");
> map.set(2, "c");
> map.set(3, "d");

> logIterator(map.entries());
[0, "a"]
[1, "b"]
[2, "c"]
[3, "d"]

> logIterator(map.keys());
0
1
2
3

> logIterator(map.values());
a
b
c
d
> var map = new Map();
> map.set(0, "a");
> map.set(1, "b");
> map.set(2, "c");
> map.set(3, "d");

> for (data of map.entries()) {
    console.log(data);
}
[0, "a"]
[1, "b"]
[2, "c"]
[3, "d"]
// w/ Laziness 
table[Symbol.iterator] = function () {
  var keys = Object.keys(this).sort();
  var index = 0;
  
  return {
    next: function () {
      return {
        value: keys[index], done: index++ &gt;= keys.length
      };
    }
  }
}

// w/ Laziness => sort is only calculates when first next() 
table[Symbol.iterator] = function () {
  var _this = this;
  var keys = null;
  var index = 0;
  
  return {
    next: function () {
      if (keys === null) {
        keys = Object.keys(_this).sort();
      }
      
      return {
        value: keys[index], done: index++ &gt;= keys.length
      };
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment