Trying Out ECMAScript.next's for...of Loop in Firefox 13
Join the DZone community and get the full member experience.
Join For Free
ECMAScript.next’s for...of loop
has been prototyped in Firefox 13. It’s a rough first implementation
that’s not yet feature-complete. This blog post explains how it works.
Iterating over arrays
The standard for...in loop has several quirks: It iterates over all enumerable properties of an object, including inherited ones. That means it is ill-suited for iterating over arrays, because it does not iterate over array elements. You cannot even use it to iterate over array indices, because non-index property names are always included. As an example, take the following array.let arr = [ "blue", "green" ]; arr.notAnIndex = 123; Array.prototype.protoProp = 456;If you iterate over it with for...in, you get:
> for(k in arr) console.log(k) 0 1 notAnIndex protoPropHence, for ECMAScript 5, it is better to use Array.prototype.forEach [1]. ECMAScript.next will give us the for...of loop that also works as expected:
> for(k of arr) console.log(k) blue green
Iterators
ECMCAScript.next iterators allow one to implement a custom iteration strategy for a data structure. To achieve the same under ECMAScript 5, one usually creates a new array and iterates over it via Array.prototype.forEach(). For example, Object.keys() can be seen as a custom iteration strategy for objects: It iterates over the enumerable own property names. However, each time it is invoked, it creates an array with the names. An iterator makes this simpler. The following is an example of an object that comes with custom iteration.let obj = { data: [ "hello", "world" ], // Custom iteration: __iterator__: function () { let index = 0; let that = this; // Return iterator object return { next: function () { if (index < that.data.length) { return that.data[index++]; } else { throw StopIteration; } } } } }The special method __iterator__ returns an iterator object. Such an object has a method next() that either returns the next element in the current iteration sequence or throws StopIteration if there are no more elements. Firefox 13’s for...of does not yet support the __iterator__ method. Once it does, one will be able to iterate over obj likes this:
> for (x of obj) console.log(x); hello worldNote that the final version of for...of will probably use a special mechanism to specify the name of the iterator method. That is, it won’t have the name __iterator__.
Generators
Among other things, generators help with implementing iterators. The above iterator could be implemented as follows via a generator:let obj = { data: [ "hello", "world" ], // function* means: generator __iterator__: function* generator() { for(let index=0; index < this.data.length; index++) { yield this.data[index]; } } }Let’s use a generator to iterate over the [property name, property value] entries of an object.
function* items(obj) { // Firefox 13: function items... for(let key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { yield [ key, obj[key] ]; } } }The above code works in Firefox 13, but you have to omit the * after function. You use items() as follows:
> let obj = { first: "Jane", last: "Doe" }; > for (x of items(obj)) console.log(x); ["first", "Jane"] ["last", "Doe"]You can also destructure the array if you are interested in keys and values:
> for ([k,v] of items(obj)) console.log(k+" = "+v); first = Jane last = Doe
Still missing
When for...of has been completely implemented, you should be able to directly iterate over objects:> let obj = { first: "Jane", last: "Doe" }; > for ([k,v] of obj) console.log(k+" = "+v); first = Jane last = DoeAnd there will be support for implementing custom iteration for any object (similar to the hypothetical __iterator__ method above).
Related reading
Object (computer science)
Published at DZone with permission of Axel Rauschmayer, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments