ECMAScript.next’s for-of loop will provide a new and quirk-free way of iterating over all kinds of data. This blog post explains how it works and how you can try out a prototype implementation in Firefox 13 and later.
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
protoProp
Hence, 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
import items from "@iter";
let obj = { first: "Jane", last: "Doe" };
for (let [k,v] of items(obj)) {
console.log(k+" = "+v);
}
Output:
first = Jane
last = Doe
Firefox does not yet have the module @iter (or modules in general), but you can use the function Iterator() as a work-around:
let obj = { first: "Jane", last: "Doe" };
for (let [k,v] of Iterator(obj)) {
console.log(k+" = "+v);
}
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 like this:
> for (x of obj) console.log(x);
hello
world
Note 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__.
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