The power of iterators in ES6

Symbols were quietly added to ES6. As a web developer, they have low use cases. But Symbol.iterator, embedded into certain object types, give developers access to ES6s new iterator.

The for...of loop
This new loop is similar to .forEach for arrays, but the main difference is that for...of loops can be used on anything with a Symbol.iterator attribute.
for (let char of "console.logged character by character") {
  console.log(char);
}
new String()[Symbol.iterator] ? true : false // true
new Array()[Symbol.iterator] ? true : false // true
new Set()[Symbol.iterator] ? true : false // true
new Map()[Symbol.iterator] ? true : false // true
This means strings, maps, sets, and arrays are all iteratable using for...of loops.

Array.from for objects that have a Symbol.iterator
Array.from is essentially a "mapped" version of what a for...of loop does.
Array.from("string") //['s', 't', 'r', 'i', 'n', 'g' ]
Array.from(new Set([1, 1, 3, 4, 5])) //[1, 3, 4, 5 ] from a set to an array

const sampleMap = new Map()
sampleMap.set(1, '1s value').set(2, '2s value').set(3, '3s value')
//Map { 1 => '1s value', 2 => '2s value', 3 => '3s value' }
Array.from(sampleMap)
//[ [1, '1s value'], [2, '2s value'], [3, '3s value'] ] key value pairs

Objects don't have a Symbol.iterator
new Object()[Symbol.iterator] ? true : false // false!?
I found this surprising, but it's easy to circumvent and still use for...of loops using Object.keys, Object.values, and Object.entries.
const sampleObject = {a: 1, b: 2, c: 3}
Object.values(sampleObject) //[1, 2, 3]
Object.keys(sampleObject) //['a', 'b', 'c']
Object.entries(sampleObject) // [ ['a', 1], ['b', 2], ['c', 3] ]

Destructure assignment for iterators
This is not exclusive to for...of loops, but it's nice to point out that the ES6 destructure assignment works on iterators for variable declaration.
const sampleMap = new Map()
sampleMap.set(1, '1s value').set(2, '2s value').set(3, '3s value')
for (let [key, val] of sampleMap) {
  console.log(key)
  console.log(val)
}

Performance
In its current state with transpilers, ES6 gets outperformed by raw ES5. In some cases it's by a lot. But in my opinion, it's usually worth it for cleanliness and maintainability. It also makes me think of this quote:
often devs still approach performance of JS code as if they are riding a horse cart but the horse had long been replaced with fusion reactor [sic]
Before I conclude, let me show you how to create an array of only unique values with the power of ES6:
const sampleArray = [1 , 2, 1, 1, 1, 11]
Array.from(new Set(sampleArray))
//or even better, using spread
[...new Set(sampleArray)]
//[1, 2, 11]

Happy coding!

Comments

Popular posts from this blog

Contrasting var and ES6s new declarations: let and const

Modularity vs. Abstraction. Which is More Important?

Unit testable components pt.3: Testing components